From bf504ae6c5b9bc25655ee543426325ba40529ed8 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 5 Nov 2021 16:58:13 +0300 Subject: [PATCH 001/275] 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" -- 2.34.1 From a1351aa9428b44965bdcb811a96115dbaca9c8ab Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 8 Nov 2021 17:50:49 +0300 Subject: [PATCH 002/275] 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.* -- 2.34.1 From 1315a8cd34102e205d75af7af8fa7b06945772ee Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 8 Nov 2021 19:57:22 +0300 Subject: [PATCH 003/275] 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 /** -- 2.34.1 From f6b576071dc2ef1c11d6b8ba1056f55065824d91 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 9 Nov 2021 12:25:17 +0300 Subject: [PATCH 004/275] 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 -- 2.34.1 From d62bc66d4ab24bdd240277a18c227f1adfee632d Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 9 Nov 2021 13:42:22 +0300 Subject: [PATCH 005/275] 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 -- 2.34.1 From fa9ff4c9787ef18cacbcb4ea38aa30bedf7de681 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 9 Nov 2021 17:56:53 +0300 Subject: [PATCH 006/275] 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 -- 2.34.1 From 9a1f8a22661302e41a47e84dd52f2ea050d7b53c Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 10 Nov 2021 11:51:20 +0300 Subject: [PATCH 007/275] 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) } /** -- 2.34.1 From 7b1bdc21a4ba5eb5d36d32afeffde7055c26f88b Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Thu, 12 Aug 2021 16:37:53 +0300 Subject: [PATCH 008/275] Copy DerivativeStructure to multiplatform --- README.md | 2 +- docs/templates/README-TEMPLATE.md | 2 +- .../kscience/kmath/expressions/DSCompiler.kt | 1541 +++++++++++++++++ .../kmath/expressions/DerivativeStructure.kt | 186 ++ .../DerivativeStructureExpression.kt | 332 ++++ .../DerivativeStructureExpressionTest.kt | 59 + .../kscience/kmath/internal/InternalUtils.kt | 3 +- 7 files changed, 2122 insertions(+), 3 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DSCompiler.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DerivativeStructure.kt create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpression.kt create mode 100644 kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpressionTest.kt diff --git a/README.md b/README.md index 92260716e..aeedfefbb 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ module definitions below. The module stability could have the following levels: * **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could break any moment. You can still use it, but be sure to fix the specific version. * **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked - with `@UnstableKmathAPI` or other stability warning annotations. + with `@UnstableKMathAPI` or other stability warning annotations. * **DEVELOPMENT**. API breaking generally follows semantic versioning ideology. There could be changes in minor versions, but not in patch versions. API is protected with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool. diff --git a/docs/templates/README-TEMPLATE.md b/docs/templates/README-TEMPLATE.md index b0c418697..2e64a3e09 100644 --- a/docs/templates/README-TEMPLATE.md +++ b/docs/templates/README-TEMPLATE.md @@ -44,7 +44,7 @@ module definitions below. The module stability could have the following levels: * **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could break any moment. You can still use it, but be sure to fix the specific version. * **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked - with `@UnstableKmathAPI` or other stability warning annotations. + with `@UnstableKMathAPI` or other stability warning annotations. * **DEVELOPMENT**. API breaking generally follows semantic versioning ideology. There could be changes in minor versions, but not in patch versions. API is protected with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool. diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DSCompiler.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DSCompiler.kt new file mode 100644 index 000000000..bb88ce52c --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DSCompiler.kt @@ -0,0 +1,1541 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + */ + +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.max +import kotlin.math.min + +internal fun MutableBuffer.fill(element: T, fromIndex: Int = 0, toIndex: Int = size) { + for (i in fromIndex until toIndex) this[i] = element +} + +/** + * Class holding "compiled" computation rules for derivative structures. + * + * This class implements the computation rules described in Dan Kalman's paper + * [Doubly Recursive Multivariate Automatic Differentiation](http://www1.american.edu/cas/mathstat/People/kalman/pdffiles/mmgautodiff.pdf), + * Mathematics Magazine, vol. 75, no. 3, June 2002. However, to avoid performances bottlenecks, the recursive rules are + * "compiled" once in an unfolded form. This class does this recursion unrolling and stores the computation rules as + * simple loops with pre-computed indirection arrays. + * + * This class maps all derivative computation into single dimension arrays that hold the value and partial derivatives. + * The class does not hold these arrays, which remains under the responsibility of the caller. For each combination of + * number of free parameters and derivation order, only one compiler is necessary, and this compiler will be used to + * perform computations on all arrays provided to it, which can represent hundreds or thousands of different parameters + * kept together with all their partial derivatives. + * + * The arrays on which compilers operate contain only the partial derivatives together with the 0th + * derivative, i.e., the value. The partial derivatives are stored in a compiler-specific order, which can be retrieved + * using methods [getPartialDerivativeIndex] and [getPartialDerivativeOrders]. The value is guaranteed to be stored as + * the first element (i.e., the [getPartialDerivativeIndex] method returns 0 when called with 0 for all derivation + * orders and [getPartialDerivativeOrders] returns an array filled with 0 when called with 0 as the index). + * + * Note that the ordering changes with number of parameters and derivation order. For example given 2 parameters x and + * y, df/dy is stored at index 2 when derivation order is set to 1 (in this case the array has three elements: f, + * df/dx and df/dy). If derivation order is set to 2, then df/dy will be stored at index 3 (in this case the array has + * six elements: f, df/dx, df/dxdx, df/dy, df/dxdy and df/dydy). + * + * Given this structure, users can perform some simple operations like adding, subtracting or multiplying constants and + * negating the elements by themselves, knowing if they want to mutate their array or create a new array. These simple + * operations are not provided by the compiler. The compiler provides only the more complex operations between several + * arrays. + * + * Derived from + * [Commons Math's `DSCompiler`](https://github.com/apache/commons-math/blob/924f6c357465b39beb50e3c916d5eb6662194175/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/analysis/differentiation/DSCompiler.java). + * + * @property freeParameters Number of free parameters. + * @property order Derivation order. + * @see DerivativeStructure + */ +internal class DSCompiler> internal constructor( + val algebra: A, + val bufferFactory: MutableBufferFactory, + val freeParameters: Int, + val order: Int, + valueCompiler: DSCompiler?, + derivativeCompiler: DSCompiler?, +) { + /** + * Number of partial derivatives (including the single 0 order derivative element). + */ + val sizes: Array by lazy { + compileSizes( + freeParameters, + order, + valueCompiler, + ) + } + + /** + * Indirection array for partial derivatives. + */ + val derivativesIndirection: Array by lazy { + compileDerivativesIndirection( + freeParameters, order, + valueCompiler, derivativeCompiler, + ) + } + + /** + * Indirection array of the lower derivative elements. + */ + val lowerIndirection: IntArray by lazy { + compileLowerIndirection( + freeParameters, order, + valueCompiler, derivativeCompiler, + ) + } + + /** + * Indirection arrays for multiplication. + */ + val multIndirection: Array> by lazy { + compileMultiplicationIndirection( + freeParameters, order, + valueCompiler, derivativeCompiler, lowerIndirection, + ) + } + + /** + * Indirection arrays for function composition. + */ + val compositionIndirection: Array> by lazy { + compileCompositionIndirection( + freeParameters, order, + valueCompiler, derivativeCompiler, + sizes, derivativesIndirection, + ) + } + + /** + * Get the array size required for holding partial derivatives' data. + * + * This number includes the single 0 order derivative element, which is + * guaranteed to be stored in the first element of the array. + */ + val size: Int + get() = sizes[freeParameters][order] + + /** + * Get the index of a partial derivative in the array. + * + * If all orders are set to 0, then the 0th order derivative is returned, which is the value of the + * function. + * + * The indices of derivatives are between 0 and [size] − 1. Their specific order is fixed for a given compiler, but + * otherwise not publicly specified. There are however some simple cases which have guaranteed indices: + * + * * the index of 0th order derivative is always 0 + * * if there is only 1 [freeParameters], then the + * derivatives are sorted in increasing derivation order (i.e., f at index 0, df/dp + * at index 1, d2f/dp2 at index 2 … + * dkf/dpk at index k), + * * if the [order] is 1, then the derivatives + * are sorted in increasing free parameter order (i.e., f at index 0, df/dx1 + * at index 1, df/dx2 at index 2 … df/dxk at index k), + * * all other cases are not publicly specified. + * + * This method is the inverse of method [getPartialDerivativeOrders]. + * + * @param orders derivation orders with respect to each parameter. + * @return index of the partial derivative. + * @see getPartialDerivativeOrders + */ + fun getPartialDerivativeIndex(vararg orders: Int): Int { + // safety check + require(orders.size == freeParameters) { "dimension mismatch: ${orders.size} and $freeParameters" } + return getPartialDerivativeIndex(freeParameters, order, sizes, *orders) + } + + /** + * Get the derivation orders for a specific index in the array. + * + * This method is the inverse of [getPartialDerivativeIndex]. + * + * @param index of the partial derivative + * @return orders derivation orders with respect to each parameter + * @see getPartialDerivativeIndex + */ + fun getPartialDerivativeOrders(index: Int): IntArray = derivativesIndirection[index] +} + +/** + * Compute natural logarithm of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for logarithm the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.ln( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int +) where A : Field, A : ExponentialOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + function[0] = ln(operand[operandOffset]) + + if (order > 0) { + val inv = one / operand[operandOffset] + var xk = inv + for (i in 1..order) { + function[i] = xk + xk *= (-i * inv) + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute integer power of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param n power to apply. + * @param result array where result must be stored (for power the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.pow( + operand: Buffer, + operandOffset: Int, + n: Int, + result: MutableBuffer, + resultOffset: Int +) where A : Field, A : PowerOperations = algebra { + if (n == 0) { + // special case, x^0 = 1 for all x + result[resultOffset] = one + result.fill(zero, resultOffset + 1, resultOffset + size) + return + } + + // create the power function value and derivatives + // [x^n, nx^(n-1), n(n-1)x^(n-2), ... ] + val function = bufferFactory(1 + order) { zero } + + if (n > 0) { + // strictly positive power + val maxOrder: Int = min(order, n) + var xk = operand[operandOffset] pow n - maxOrder + for (i in maxOrder downTo 1) { + function[i] = xk + xk *= operand[operandOffset] + } + function[0] = xk + } else { + // strictly negative power + val inv = one / operand[operandOffset] + var xk = inv pow -n + + for (i in 0..order) { + function[i] = xk + xk *= inv + } + } + + var coefficient = number(n) + + for (i in 1..order) { + function[i] = function[i] * coefficient + coefficient *= (n - i).toDouble() + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute exponential of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for exponential the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.exp( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int +) where A : Ring, A : ScaleOperations, A : ExponentialOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + function.fill(exp(operand[operandOffset])) + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute square root of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for nth root the result array *cannot* be the input + * array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.sqrt( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int +) where A : Field, A : PowerOperations = algebra { + // create the function value and derivatives + // [x^(1/n), (1/n)x^((1/n)-1), (1-n)/n^2x^((1/n)-2), ... ] + val function = bufferFactory(1 + order) { zero } + function[0] = sqrt(operand[operandOffset]) + var xk: T = 0.5 * one / function[0] + val xReciprocal = one / operand[operandOffset] + + for (i in 1..order) { + function[i] = xk + xk *= xReciprocal * (0.5 - i) + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute cosine of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for cosine the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.cos( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Ring, A : TrigonometricOperations, A : ScaleOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + function[0] = cos(operand[operandOffset]) + + if (order > 0) { + function[1] = -sin(operand[operandOffset]) + for (i in 2..order) { + function[i] = -function[i - 2] + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute power of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param p power to apply. + * @param result array where result must be stored (for power the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.pow( + operand: Buffer, + operandOffset: Int, + p: Double, + result: MutableBuffer, + resultOffset: Int +) where A : Ring, A : NumericAlgebra, A : PowerOperations, A : ScaleOperations = algebra { + // create the function value and derivatives + // [x^p, px^(p-1), p(p-1)x^(p-2), ... ] + val function = bufferFactory(1 + order) { zero } + var xk = operand[operandOffset] pow p - order + + for (i in order downTo 1) { + function[i] = xk + xk *= operand[operandOffset] + } + + function[0] = xk + var coefficient = p + + for (i in 1..order) { + function[i] = function[i] * coefficient + coefficient *= p - i + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute tangent of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for tangent the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.tan( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int +) where A : Ring, A : TrigonometricOperations, A : ScaleOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + val t = tan(operand[operandOffset]) + function[0] = t + + if (order > 0) { + + // the nth order derivative of tan has the form: + // dn(tan(x)/dxn = P_n(tan(x)) + // where P_n(t) is a degree n+1 polynomial with same parity as n+1 + // P_0(t) = t, P_1(t) = 1 + t^2, P_2(t) = 2 t (1 + t^2) ... + // the general recurrence relation for P_n is: + // P_n(x) = (1+t^2) P_(n-1)'(t) + // as per polynomial parity, we can store coefficients of both P_(n-1) and P_n in the same array + val p = bufferFactory(order + 2) { zero } + p[1] = one + val t2 = t * t + for (n in 1..order) { + + // update and evaluate polynomial P_n(t) + var v = one + p[n + 1] = n * p[n] + var k = n + 1 + while (k >= 0) { + v = v * t2 + p[k] + if (k > 2) { + p[k - 2] = (k - 1) * p[k - 1] + (k - 3) * p[k - 3] + } else if (k == 2) { + p[0] = p[1] + } + k -= 2 + } + if (n and 0x1 == 0) { + v *= t + } + function[n] = v + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute power of a derivative structure. + * + * @param x array holding the base. + * @param xOffset offset of the base in its array. + * @param y array holding the exponent. + * @param yOffset offset of the exponent in its array. + * @param result array where result must be stored (for power the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.pow( + x: Buffer, + xOffset: Int, + y: Buffer, + yOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Field, A : ExponentialOperations = algebra { + val logX = bufferFactory(size) { zero } + ln(x, xOffset, logX, 0) + val yLogX = bufferFactory(size) { zero } + multiply(logX, 0, y, yOffset, yLogX, 0) + exp(yLogX, 0, result, resultOffset) +} + +/** + * Compute sine of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for sine the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.sin( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int +) where A : Ring, A : ScaleOperations, A : TrigonometricOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + function[0] = sin(operand[operandOffset]) + if (order > 0) { + function[1] = cos(operand[operandOffset]) + for (i in 2..order) { + function[i] = -function[i - 2] + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute arc cosine of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for arc cosine the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.acos( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int +) where A : Field, A : TrigonometricOperations, A : PowerOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + val x = operand[operandOffset] + function[0] = acos(x) + if (order > 0) { + // the nth order derivative of acos has the form: + // dn(acos(x)/dxn = P_n(x) / [1 - x^2]^((2n-1)/2) + // where P_n(x) is a degree n-1 polynomial with same parity as n-1 + // P_1(x) = -1, P_2(x) = -x, P_3(x) = -2x^2 - 1 ... + // the general recurrence relation for P_n is: + // P_n(x) = (1-x^2) P_(n-1)'(x) + (2n-3) x P_(n-1)(x) + // as per polynomial parity, we can store coefficients of both P_(n-1) and P_n in the same array + val p = bufferFactory(order) { zero } + p[0] = -one + val x2 = x * x + val f = one / (one - x2) + var coeff = sqrt(f) + function[1] = coeff * p[0] + + for (n in 2..order) { + // update and evaluate polynomial P_n(x) + var v = zero + p[n - 1] = (n - 1) * p[n - 2] + var k = n - 1 + + while (k >= 0) { + v = v * x2 + p[k] + if (k > 2) { + p[k - 2] = (k - 1) * p[k - 1] + (2 * n - k) * p[k - 3] + } else if (k == 2) { + p[0] = p[1] + } + k -= 2 + } + + if (n and 0x1 == 0) { + v *= x + } + + coeff *= f + function[n] = coeff * v + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute arc sine of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for arc sine the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.asin( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int +) where A : Field, A : TrigonometricOperations, A : PowerOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + val x = operand[operandOffset] + function[0] = asin(x) + if (order > 0) { + // the nth order derivative of asin has the form: + // dn(asin(x)/dxn = P_n(x) / [1 - x^2]^((2n-1)/2) + // where P_n(x) is a degree n-1 polynomial with same parity as n-1 + // P_1(x) = 1, P_2(x) = x, P_3(x) = 2x^2 + 1 ... + // the general recurrence relation for P_n is: + // P_n(x) = (1-x^2) P_(n-1)'(x) + (2n-3) x P_(n-1)(x) + // as per polynomial parity, we can store coefficients of both P_(n-1) and P_n in the same array + val p = bufferFactory(order) { zero } + p[0] = one + val x2 = x * x + val f = one / (one - x2) + var coeff = sqrt(f) + function[1] = coeff * p[0] + for (n in 2..order) { + + // update and evaluate polynomial P_n(x) + var v = zero + p[n - 1] = (n - 1) * p[n - 2] + var k = n - 1 + while (k >= 0) { + v = v * x2 + p[k] + if (k > 2) { + p[k - 2] = (k - 1) * p[k - 1] + (2 * n - k) * p[k - 3] + } else if (k == 2) { + p[0] = p[1] + } + k -= 2 + } + if (n and 0x1 == 0) { + v *= x + } + coeff *= f + function[n] = coeff * v + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute arc tangent of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for arc tangent the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.atan( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int +) where A : Field, A : TrigonometricOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + val x = operand[operandOffset] + function[0] = atan(x) + + if (order > 0) { + // the nth order derivative of atan has the form: + // dn(atan(x)/dxn = Q_n(x) / (1 + x^2)^n + // where Q_n(x) is a degree n-1 polynomial with same parity as n-1 + // Q_1(x) = 1, Q_2(x) = -2x, Q_3(x) = 6x^2 - 2 ... + // the general recurrence relation for Q_n is: + // Q_n(x) = (1+x^2) Q_(n-1)'(x) - 2(n-1) x Q_(n-1)(x) + // as per polynomial parity, we can store coefficients of both Q_(n-1) and Q_n in the same array + val q = bufferFactory(order) { zero } + q[0] = one + val x2 = x * x + val f = one / (one + x2) + var coeff = f + function[1] = coeff * q[0] + for (n in 2..order) { + + // update and evaluate polynomial Q_n(x) + var v = zero + q[n - 1] = -n * q[n - 2] + var k = n - 1 + while (k >= 0) { + v = v * x2 + q[k] + if (k > 2) { + q[k - 2] = (k - 1) * q[k - 1] + (k - 1 - 2 * n) * q[k - 3] + } else if (k == 2) { + q[0] = q[1] + } + k -= 2 + } + if (n and 0x1 == 0) { + v *= x + } + coeff *= f + function[n] = coeff * v + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute hyperbolic cosine of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for hyperbolic cosine the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.cosh( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int +) where A : Ring, A : ScaleOperations, A : ExponentialOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + function[0] = cosh(operand[operandOffset]) + + if (order > 0) { + function[1] = sinh(operand[operandOffset]) + for (i in 2..order) { + function[i] = function[i - 2] + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute hyperbolic tangent of a derivative structure. + * + * @param operand array holding the operand + * @param operandOffset offset of the operand in its array + * @param result array where result must be stored (for hyperbolic tangent the result array *cannot* be the input + * array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.tanh( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int +) where A : Field, A : ExponentialOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + val t = tanh(operand[operandOffset]) + function[0] = t + if (order > 0) { + + // the nth order derivative of tanh has the form: + // dn(tanh(x)/dxn = P_n(tanh(x)) + // where P_n(t) is a degree n+1 polynomial with same parity as n+1 + // P_0(t) = t, P_1(t) = 1 - t^2, P_2(t) = -2 t (1 - t^2) ... + // the general recurrence relation for P_n is: + // P_n(x) = (1-t^2) P_(n-1)'(t) + // as per polynomial parity, we can store coefficients of both P_(n-1) and P_n in the same array + val p = bufferFactory(order + 2) { zero } + p[1] = one + val t2 = t * t + for (n in 1..order) { + + // update and evaluate polynomial P_n(t) + var v = zero + p[n + 1] = -n * p[n] + var k = n + 1 + while (k >= 0) { + v = v * t2 + p[k] + if (k > 2) { + p[k - 2] = (k - 1) * p[k - 1] - (k - 3) * p[k - 3] + } else if (k == 2) { + p[0] = p[1] + } + k -= 2 + } + if (n and 0x1 == 0) { + v *= t + } + function[n] = v + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute inverse hyperbolic cosine of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for inverse hyperbolic cosine the result array *cannot* be the input + * array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.acosh( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int +) where A : Field, A : ExponentialOperations, A : PowerOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + val x = operand[operandOffset] + function[0] = acosh(x) + + if (order > 0) { + // the nth order derivative of acosh has the form: + // dn(acosh(x)/dxn = P_n(x) / [x^2 - 1]^((2n-1)/2) + // where P_n(x) is a degree n-1 polynomial with same parity as n-1 + // P_1(x) = 1, P_2(x) = -x, P_3(x) = 2x^2 + 1 ... + // the general recurrence relation for P_n is: + // P_n(x) = (x^2-1) P_(n-1)'(x) - (2n-3) x P_(n-1)(x) + // as per polynomial parity, we can store coefficients of both P_(n-1) and P_n in the same array + val p = bufferFactory(order) { zero } + p[0] = one + val x2 = x * x + val f = one / (x2 - one) + var coeff = sqrt(f) + function[1] = coeff * p[0] + for (n in 2..order) { + + // update and evaluate polynomial P_n(x) + var v = zero + p[n - 1] = (1 - n) * p[n - 2] + var k = n - 1 + while (k >= 0) { + v = v * x2 + p[k] + if (k > 2) { + p[k - 2] = (1 - k) * p[k - 1] + (k - 2 * n) * p[k - 3] + } else if (k == 2) { + p[0] = -p[1] + } + k -= 2 + } + if (n and 0x1 == 0) { + v *= x + } + + coeff *= f + function[n] = coeff * v + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Compute composition of a derivative structure by a function. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param f array of value and derivatives of the function at the current point (i.e. at `operand[operandOffset]`). + * @param result array where result must be stored (for composition the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.compose( + operand: Buffer, + operandOffset: Int, + f: Buffer, + result: MutableBuffer, + resultOffset: Int, +) where A : Ring, A : ScaleOperations = algebra { + for (i in compositionIndirection.indices) { + val mappingI = compositionIndirection[i] + var r = zero + for (j in mappingI.indices) { + val mappingIJ = mappingI[j] + var product = mappingIJ[0] * f[mappingIJ[1]] + for (k in 2 until mappingIJ.size) { + product *= operand[operandOffset + mappingIJ[k]] + } + r += product + } + result[resultOffset + i] = r + } +} + +/** + * Compute hyperbolic sine of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for hyperbolic sine the result array *cannot* be the input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.sinh( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int +) where A : Field, A : ExponentialOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + function[0] = sinh(operand[operandOffset]) + + if (order > 0) { + function[1] = cosh(operand[operandOffset]) + for (i in 2..order) { + function[i] = function[i - 2] + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Perform division of two derivative structures. + * + * @param lhs array holding left-hand side of division. + * @param lhsOffset offset of the left-hand side in its array. + * @param rhs array right-hand side of division. + * @param rhsOffset offset of the right-hand side in its array. + * @param result array where result must be stored (for division the result array *cannot* be one of the input arrays). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.divide( + lhs: Buffer, + lhsOffset: Int, + rhs: Buffer, + rhsOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Field, A : PowerOperations, A : ScaleOperations = algebra { + val reciprocal = bufferFactory(size) { zero } + pow(rhs, lhsOffset, -1, reciprocal, 0) + multiply(lhs, lhsOffset, reciprocal, rhsOffset, result, resultOffset) +} + +/** + * Perform multiplication of two derivative structures. + * + * @param lhs array holding left-hand side of multiplication. + * @param lhsOffset offset of the left-hand side in its array. + * @param rhs array right-hand side of multiplication. + * @param rhsOffset offset of the right-hand side in its array. + * @param result array where result must be stored (for multiplication the result array *cannot* be one of the input + * arrays). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.multiply( + lhs: Buffer, + lhsOffset: Int, + rhs: Buffer, + rhsOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Ring, A : ScaleOperations = algebra { + for (i in multIndirection.indices) { + val mappingI = multIndirection[i] + var r = zero + + for (j in mappingI.indices) { + r += mappingI[j][0] * lhs[lhsOffset + mappingI[j][1]] * rhs[rhsOffset + mappingI[j][2]] + } + + result[resultOffset + i] = r + } +} + +/** + * Perform subtraction of two derivative structures. + * + * @param lhs array holding left-hand side of subtraction. + * @param lhsOffset offset of the left-hand side in its array. + * @param rhs array right-hand side of subtraction. + * @param rhsOffset offset of the right-hand side in its array. + * @param result array where result must be stored (it may be one of the input arrays). + * @param resultOffset offset of the result in its array. + */ +internal fun > DSCompiler.subtract( + lhs: Buffer, + lhsOffset: Int, + rhs: Buffer, + rhsOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) = algebra { + for (i in 0 until size) { + result[resultOffset + i] = lhs[lhsOffset + i] - rhs[rhsOffset + i] + } +} + +/** + * Compute inverse hyperbolic sine of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for inverse hyperbolic sine the result array *cannot* be the input + * array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.asinh( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int +) where A : Field, A : ExponentialOperations, A : PowerOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + val x = operand[operandOffset] + function[0] = asinh(x) + if (order > 0) { + // the nth order derivative of asinh has the form: + // dn(asinh(x)/dxn = P_n(x) / [x^2 + 1]^((2n-1)/2) + // where P_n(x) is a degree n-1 polynomial with same parity as n-1 + // P_1(x) = 1, P_2(x) = -x, P_3(x) = 2x^2 - 1 ... + // the general recurrence relation for P_n is: + // P_n(x) = (x^2+1) P_(n-1)'(x) - (2n-3) x P_(n-1)(x) + // as per polynomial parity, we can store coefficients of both P_(n-1) and P_n in the same array + val p = bufferFactory(order) { zero } + p[0] = one + val x2 = x * x + val f = one / (one + x2) + var coeff = sqrt(f) + function[1] = coeff * p[0] + for (n in 2..order) { + + // update and evaluate polynomial P_n(x) + var v = zero + p[n - 1] = (1 - n) * p[n - 2] + var k = n - 1 + while (k >= 0) { + v = v * x2 + p[k] + if (k > 2) { + p[k - 2] = (k - 1) * p[k - 1] + (k - 2 * n) * p[k - 3] + } else if (k == 2) { + p[0] = p[1] + } + k -= 2 + } + if (n and 0x1 == 0) { + v *= x + } + coeff *= f + function[n] = coeff * v + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Perform addition of two derivative structures. + * + * @param lhs array holding left-hand side of addition. + * @param lhsOffset offset of the left-hand side in its array. + * @param rhs array right-hand side of addition. + * @param rhsOffset offset of the right-hand side in its array. + * @param result array where result must be stored (it may be one of the input arrays). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.add( + lhs: Buffer, + lhsOffset: Int, + rhs: Buffer, + rhsOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Group = algebra { + for (i in 0 until size) { + result[resultOffset + i] = lhs[lhsOffset + i] + rhs[rhsOffset + i] + } +} + +/** + * Check rules set compatibility. + * + * @param compiler other compiler to check against instance. + */ +internal fun > DSCompiler.checkCompatibility(compiler: DSCompiler) { + require(freeParameters == compiler.freeParameters) { + "dimension mismatch: $freeParameters and ${compiler.freeParameters}" + } + require(order == compiler.order) { + "dimension mismatch: $order and ${compiler.order}" + } +} + +/** + * Compute inverse hyperbolic tangent of a derivative structure. + * + * @param operand array holding the operand. + * @param operandOffset offset of the operand in its array. + * @param result array where result must be stored (for inverse hyperbolic tangent the result array *cannot* be the + * input array). + * @param resultOffset offset of the result in its array. + */ +internal fun DSCompiler.atanh( + operand: Buffer, + operandOffset: Int, + result: MutableBuffer, + resultOffset: Int, +) where A : Field, A : ExponentialOperations = algebra { + // create the function value and derivatives + val function = bufferFactory(1 + order) { zero } + val x = operand[operandOffset] + function[0] = atanh(x) + + if (order > 0) { + // the nth order derivative of atanh has the form: + // dn(atanh(x)/dxn = Q_n(x) / (1 - x^2)^n + // where Q_n(x) is a degree n-1 polynomial with same parity as n-1 + // Q_1(x) = 1, Q_2(x) = 2x, Q_3(x) = 6x^2 + 2 ... + // the general recurrence relation for Q_n is: + // Q_n(x) = (1-x^2) Q_(n-1)'(x) + 2(n-1) x Q_(n-1)(x) + // as per polynomial parity, we can store coefficients of both Q_(n-1) and Q_n in the same array + val q = bufferFactory(order) { zero } + q[0] = one + val x2 = x * x + val f = one / (one - x2) + var coeff = f + function[1] = coeff * q[0] + for (n in 2..order) { + + // update and evaluate polynomial Q_n(x) + var v = zero + q[n - 1] = n * q[n - 2] + var k = n - 1 + while (k >= 0) { + v = v * x2 + q[k] + if (k > 2) { + q[k - 2] = (k - 1) * q[k - 1] + (2 * n - k + 1) * q[k - 3] + } else if (k == 2) { + q[0] = q[1] + } + k -= 2 + } + if (n and 0x1 == 0) { + v *= x + } + coeff *= f + function[n] = coeff * v + } + } + + // apply function composition + compose(operand, operandOffset, function, result, resultOffset) +} + +/** + * Get the compiler for number of free parameters and order. + * + * @param parameters number of free parameters. + * @param order derivation order. + * @return cached rules set. + */ +internal fun > getCompiler( + algebra: A, + bufferFactory: MutableBufferFactory, + parameters: Int, + order: Int +): DSCompiler { + // get the cached compilers + val cache: Array?>>? = null + + // we need to create more compilers + val maxParameters: Int = max(parameters, cache?.size ?: 0) + val maxOrder: Int = max(order, if (cache == null) 0 else cache[0].size) + val newCache: Array?>> = Array(maxParameters + 1) { arrayOfNulls(maxOrder + 1) } + + if (cache != null) { + // preserve the already created compilers + for (i in cache.indices) { + cache[i].copyInto(newCache[i], endIndex = cache[i].size) + } + } + + // create the array in increasing diagonal order + + // create the array in increasing diagonal order + for (diag in 0..parameters + order) { + for (o in max(0, diag - parameters)..min(order, diag)) { + val p: Int = diag - o + if (newCache[p][o] == null) { + val valueCompiler: DSCompiler? = if (p == 0) null else newCache[p - 1][o]!! + val derivativeCompiler: DSCompiler? = if (o == 0) null else newCache[p][o - 1]!! + + newCache[p][o] = DSCompiler( + algebra, + bufferFactory, + p, + o, + valueCompiler, + derivativeCompiler, + ) + } + } + } + + return newCache[parameters][order]!! +} + +/** + * Compile the sizes array. + * + * @param parameters number of free parameters. + * @param order derivation order. + * @param valueCompiler compiler for the value part. + * @return sizes array. + */ +private fun > compileSizes( + parameters: Int, order: Int, + valueCompiler: DSCompiler?, +): Array { + val sizes = Array(parameters + 1) { + IntArray(order + 1) + } + + if (parameters == 0) { + sizes[0].fill(1) + } else { + checkNotNull(valueCompiler) + valueCompiler.sizes.copyInto(sizes, endIndex = parameters) + sizes[parameters][0] = 1 + for (i in 0 until order) { + sizes[parameters][i + 1] = sizes[parameters][i] + sizes[parameters - 1][i + 1] + } + } + return sizes +} + +/** + * Compile the derivatives' indirection array. + * + * @param parameters number of free parameters. + * @param order derivation order. + * @param valueCompiler compiler for the value part. + * @param derivativeCompiler compiler for the derivative part. + * @return derivatives indirection array. + */ +private fun > compileDerivativesIndirection( + parameters: Int, + order: Int, + valueCompiler: DSCompiler?, + derivativeCompiler: DSCompiler?, +): Array { + if (parameters == 0 || order == 0) { + return Array(1) { IntArray(parameters) } + } + + val vSize: Int = valueCompiler!!.derivativesIndirection.size + val dSize: Int = derivativeCompiler!!.derivativesIndirection.size + val derivativesIndirection = Array(vSize + dSize) { IntArray(parameters) } + + // set up the indices for the value part + for (i in 0 until vSize) { + // copy the first indices, the last one remaining set to 0 + valueCompiler.derivativesIndirection[i].copyInto(derivativesIndirection[i], endIndex = parameters - 1) + } + + // set up the indices for the derivative part + for (i in 0 until dSize) { + // copy the indices + derivativeCompiler.derivativesIndirection[i].copyInto(derivativesIndirection[vSize], 0, 0, parameters) + + // increment the derivation order for the last parameter + derivativesIndirection[vSize + i][parameters - 1]++ + } + + return derivativesIndirection +} + +/** + * Compile the lower derivatives' indirection array. + * + * This indirection array contains the indices of all elements except derivatives for last derivation order. + * + * @param parameters number of free parameters. + * @param order derivation order. + * @param valueCompiler compiler for the value part. + * @param derivativeCompiler compiler for the derivative part. + * @return lower derivatives' indirection array. + */ +private fun > compileLowerIndirection( + parameters: Int, + order: Int, + valueCompiler: DSCompiler?, + derivativeCompiler: DSCompiler?, +): IntArray { + if (parameters == 0 || order <= 1) return intArrayOf(0) + checkNotNull(valueCompiler) + checkNotNull(derivativeCompiler) + + // this is an implementation of definition 6 in Dan Kalman's paper. + val vSize: Int = valueCompiler.lowerIndirection.size + val dSize: Int = derivativeCompiler.lowerIndirection.size + val lowerIndirection = IntArray(vSize + dSize) + valueCompiler.lowerIndirection.copyInto(lowerIndirection, endIndex = vSize) + for (i in 0 until dSize) { + lowerIndirection[vSize + i] = valueCompiler.size + derivativeCompiler.lowerIndirection[i] + } + return lowerIndirection +} + +/** + * Compile the multiplication indirection array. + * + * This indirection array contains the indices of all pairs of elements involved when computing a multiplication. This + * allows a straightforward loop-based multiplication (see [multiply]). + * + * @param parameters number of free parameters. + * @param order derivation order. + * @param valueCompiler compiler for the value part. + * @param derivativeCompiler compiler for the derivative part. + * @param lowerIndirection lower derivatives' indirection array. + * @return multiplication indirection array. + */ +@Suppress("UNCHECKED_CAST") +private fun > compileMultiplicationIndirection( + parameters: Int, + order: Int, + valueCompiler: DSCompiler?, + derivativeCompiler: DSCompiler?, + lowerIndirection: IntArray, +): Array> { + if (parameters == 0 || order == 0) return arrayOf(arrayOf(intArrayOf(1, 0, 0))) + + // this is an implementation of definition 3 in Dan Kalman's paper. + val vSize = valueCompiler!!.multIndirection.size + val dSize = derivativeCompiler!!.multIndirection.size + val multIndirection: Array?> = arrayOfNulls(vSize + dSize) + valueCompiler.multIndirection.copyInto(multIndirection, endIndex = vSize) + + for (i in 0 until dSize) { + val dRow = derivativeCompiler.multIndirection[i] + val row: List = buildList(dRow.size * 2) { + for (j in dRow.indices) { + add(intArrayOf(dRow[j][0], lowerIndirection[dRow[j][1]], vSize + dRow[j][2])) + add(intArrayOf(dRow[j][0], vSize + dRow[j][1], lowerIndirection[dRow[j][2]])) + } + } + + // combine terms with similar derivation orders + val combined: List = buildList(row.size) { + for (j in row.indices) { + val termJ = row[j] + if (termJ[0] > 0) { + for (k in j + 1 until row.size) { + val termK = row[k] + + if (termJ[1] == termK[1] && termJ[2] == termK[2]) { + // combine termJ and termK + termJ[0] += termK[0] + // make sure we will skip termK later on in the outer loop + termK[0] = 0 + } + } + + add(termJ) + } + } + } + + multIndirection[vSize + i] = combined.toTypedArray() + } + + return multIndirection as Array> +} + +/** + * Compile the indirection array of function composition. + * + * This indirection array contains the indices of all sets of elements involved when computing a composition. This + * allows a straightforward loop-based composition (see [compose]). + * + * @param parameters number of free parameters. + * @param order derivation order. + * @param valueCompiler compiler for the value part. + * @param derivativeCompiler compiler for the derivative part. + * @param sizes sizes array. + * @param derivativesIndirection derivatives indirection array. + * @return multiplication indirection array. + */ +@Suppress("UNCHECKED_CAST") +private fun > compileCompositionIndirection( + parameters: Int, + order: Int, + valueCompiler: DSCompiler?, + derivativeCompiler: DSCompiler?, + sizes: Array, + derivativesIndirection: Array, +): Array> { + if (parameters == 0 || order == 0) { + return arrayOf(arrayOf(intArrayOf(1, 0))) + } + + val vSize = valueCompiler!!.compositionIndirection.size + val dSize = derivativeCompiler!!.compositionIndirection.size + val compIndirection: Array?> = arrayOfNulls(vSize + dSize) + + // the composition rules from the value part can be reused as is + valueCompiler.compositionIndirection.copyInto(compIndirection, endIndex = vSize) + + // the composition rules for the derivative part are deduced by differentiation the rules from the + // underlying compiler once with respect to the parameter this compiler handles and the underlying one + // did not handle + + // the composition rules for the derivative part are deduced by differentiation the rules from the + // underlying compiler once with respect to the parameter this compiler handles and the underlying one did + // not handle + for (i in 0 until dSize) { + val row: List = buildList { + for (term in derivativeCompiler.compositionIndirection[i]) { + + // handle term p * f_k(g(x)) * g_l1(x) * g_l2(x) * ... * g_lp(x) + + // derive the first factor in the term: f_k with respect to new parameter + val derivedTermF = IntArray(term.size + 1) + derivedTermF[0] = term[0] // p + derivedTermF[1] = term[1] + 1 // f_(k+1) + val orders = IntArray(parameters) + orders[parameters - 1] = 1 + derivedTermF[term.size] = getPartialDerivativeIndex( + parameters, + order, + sizes, + *orders + ) // g_1 + + for (j in 2 until term.size) { + // convert the indices as the mapping for the current order is different from the mapping with one + // less order + derivedTermF[j] = convertIndex( + term[j], parameters, + derivativeCompiler.derivativesIndirection, + parameters, order, sizes + ) + } + + derivedTermF.sort(2, derivedTermF.size) + add(derivedTermF) + + // derive the various g_l + for (l in 2 until term.size) { + val derivedTermG = IntArray(term.size) + derivedTermG[0] = term[0] + derivedTermG[1] = term[1] + + for (j in 2 until term.size) { + // convert the indices as the mapping for the current order + // is different from the mapping with one less order + derivedTermG[j] = convertIndex( + term[j], + parameters, + derivativeCompiler.derivativesIndirection, + parameters, + order, + sizes, + ) + + if (j == l) { + // derive this term + derivativesIndirection[derivedTermG[j]].copyInto(orders, endIndex = parameters) + orders[parameters - 1]++ + + derivedTermG[j] = getPartialDerivativeIndex( + parameters, + order, + sizes, + *orders, + ) + } + } + + derivedTermG.sort(2, derivedTermG.size) + add(derivedTermG) + } + } + } + + // combine terms with similar derivation orders + val combined: List = buildList(row.size) { + for (j in row.indices) { + val termJ = row[j] + + if (termJ[0] > 0) { + (j + 1 until row.size).map { k -> row[k] }.forEach { termK -> + var equals = termJ.size == termK.size + var l = 1 + + while (equals && l < termJ.size) { + equals = equals and (termJ[l] == termK[l]) + ++l + } + + if (equals) { + // combine termJ and termK + termJ[0] += termK[0] + // make sure we will skip termK later on in the outer loop + termK[0] = 0 + } + } + + add(termJ) + } + } + } + + compIndirection[vSize + i] = combined.toTypedArray() + } + + return compIndirection as Array> +} + +/** + * Get the index of a partial derivative in an array. + * + * @param parameters number of free parameters. + * @param order derivation order. + * @param sizes sizes array. + * @param orders derivation orders with respect to each parameter (the length of this array must match the number of + * parameters). + * @return index of the partial derivative. + */ +private fun getPartialDerivativeIndex( + parameters: Int, + order: Int, + sizes: Array, + vararg orders: Int, +): Int { + + // the value is obtained by diving into the recursive Dan Kalman's structure + // this is theorem 2 of his paper, with recursion replaced by iteration + var index = 0 + var m = order + var ordersSum = 0 + + for (i in parameters - 1 downTo 0) { + // derivative order for current free parameter + var derivativeOrder = orders[i] + + // safety check + ordersSum += derivativeOrder + require(ordersSum <= order) { "number is too large: $ordersSum > $order" } + + while (derivativeOrder-- > 0) { + // as long as we differentiate according to current free parameter, + // we have to skip the value part and dive into the derivative part, + // so we add the size of the value part to the base index + index += sizes[i][m--] + } + } + + return index +} + +/** + * Convert an index from one (parameters, order) structure to another. + * + * @param index index of a partial derivative in source derivative structure. + * @param srcP number of free parameters in source derivative structure. + * @param srcDerivativesIndirection derivatives indirection array for the source derivative structure. + * @param destP number of free parameters in destination derivative structure. + * @param destO derivation order in destination derivative structure. + * @param destSizes sizes array for the destination derivative structure. + * @return index of the partial derivative with the *same* characteristics in destination derivative structure. + */ +private fun convertIndex( + index: Int, + srcP: Int, + srcDerivativesIndirection: Array, + destP: Int, + destO: Int, + destSizes: Array, +): Int { + val orders = IntArray(destP) + srcDerivativesIndirection[index].copyInto(orders, endIndex = min(srcP, destP)) + return getPartialDerivativeIndex(destP, destO, destSizes, *orders) +} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DerivativeStructure.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DerivativeStructure.kt new file mode 100644 index 000000000..a1a6354f0 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DerivativeStructure.kt @@ -0,0 +1,186 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + */ + +package space.kscience.kmath.expressions + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.NumericAlgebra +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.ScaleOperations +import space.kscience.kmath.structures.MutableBuffer + +/** + * Class representing both the value and the differentials of a function. + * + * This class is the workhorse of the differentiation package. + * + * This class is an implementation of the extension to Rall's numbers described in Dan Kalman's paper [Doubly Recursive + * Multivariate Automatic Differentiation](http://www1.american.edu/cas/mathstat/People/kalman/pdffiles/mmgautodiff.pdf), + * Mathematics Magazine, vol. 75, no. 3, June 2002. Rall's numbers are an extension to the real numbers used + * throughout mathematical expressions; they hold the derivative together with the value of a function. Dan Kalman's + * derivative structures hold all partial derivatives up to any specified order, with respect to any number of free + * parameters. Rall's numbers therefore can be seen as derivative structures for order one derivative and one free + * parameter, and real numbers can be seen as derivative structures with zero order derivative and no free parameters. + * + * Derived from + * [Commons Math's `DerivativeStructure`](https://github.com/apache/commons-math/blob/924f6c357465b39beb50e3c916d5eb6662194175/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/analysis/differentiation/DerivativeStructure.java). + */ +@UnstableKMathAPI +public open class DerivativeStructure internal constructor( + internal val derivativeAlgebra: DerivativeStructureRing, + internal val compiler: DSCompiler, +) where A : Ring, A : NumericAlgebra, A : ScaleOperations { + /** + * Combined array holding all values. + */ + internal var data: MutableBuffer = + derivativeAlgebra.bufferFactory(compiler.size) { derivativeAlgebra.algebra.zero } + + /** + * Build an instance with all values and derivatives set to 0. + * + * @param parameters number of free parameters. + * @param order derivation order. + */ + public constructor ( + derivativeAlgebra: DerivativeStructureRing, + parameters: Int, + order: Int, + ) : this( + derivativeAlgebra, + getCompiler(derivativeAlgebra.algebra, derivativeAlgebra.bufferFactory, parameters, order), + ) + + /** + * Build an instance representing a constant value. + * + * @param parameters number of free parameters. + * @param order derivation order. + * @param value value of the constant. + * @see DerivativeStructure + */ + public constructor ( + derivativeAlgebra: DerivativeStructureRing, + parameters: Int, + order: Int, + value: T, + ) : this( + derivativeAlgebra, + parameters, + order, + ) { + data[0] = value + } + + /** + * Build an instance representing a variable. + * + * Instances built using this constructor are considered to be the free variables with respect to which + * differentials are computed. As such, their differential with respect to themselves is +1. + * + * @param parameters number of free parameters. + * @param order derivation order. + * @param index index of the variable (from 0 to `parameters - 1`). + * @param value value of the variable. + */ + public constructor ( + derivativeAlgebra: DerivativeStructureRing, + parameters: Int, + order: Int, + index: Int, + value: T, + ) : this(derivativeAlgebra, parameters, order, value) { + require(index < parameters) { "number is too large: $index >= $parameters" } + + if (order > 0) { + // the derivative of the variable with respect to itself is 1. + data[getCompiler(derivativeAlgebra.algebra, derivativeAlgebra.bufferFactory, index, order).size] = + derivativeAlgebra.algebra.one + } + } + + /** + * Build an instance from all its derivatives. + * + * @param parameters number of free parameters. + * @param order derivation order. + * @param derivatives derivatives sorted according to [DSCompiler.getPartialDerivativeIndex]. + */ + public constructor ( + derivativeAlgebra: DerivativeStructureRing, + parameters: Int, + order: Int, + vararg derivatives: T, + ) : this( + derivativeAlgebra, + parameters, + order, + ) { + require(derivatives.size == data.size) { "dimension mismatch: ${derivatives.size} and ${data.size}" } + data = derivativeAlgebra.bufferFactory(data.size) { derivatives[it] } + } + + /** + * Copy constructor. + * + * @param ds instance to copy. + */ + internal constructor(ds: DerivativeStructure) : this(ds.derivativeAlgebra, ds.compiler) { + this.data = ds.data.copy() + } + + /** + * The number of free parameters. + */ + public val freeParameters: Int + get() = compiler.freeParameters + + /** + * The derivation order. + */ + public val order: Int + get() = compiler.order + + /** + * The value part of the derivative structure. + * + * @see getPartialDerivative + */ + public val value: T + get() = data[0] + + /** + * Get a partial derivative. + * + * @param orders derivation orders with respect to each variable (if all orders are 0, the value is returned). + * @return partial derivative. + * @see value + */ + public fun getPartialDerivative(vararg orders: Int): T = data[compiler.getPartialDerivativeIndex(*orders)] + + + /** + * Test for the equality of two derivative structures. + * + * Derivative structures are considered equal if they have the same number + * of free parameters, the same derivation order, and the same derivatives. + * + * @return `true` if two derivative structures are equal. + */ + public override fun equals(other: Any?): Boolean { + if (this === other) return true + + if (other is DerivativeStructure<*, *>) { + return ((freeParameters == other.freeParameters) && + (order == other.order) && + data == other.data) + } + + return false + } + + public override fun hashCode(): Int = + 227 + 229 * freeParameters + 233 * order + 239 * data.hashCode() +} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpression.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpression.kt new file mode 100644 index 000000000..f91fb55e8 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpression.kt @@ -0,0 +1,332 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + */ + +package space.kscience.kmath.expressions + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.* +import space.kscience.kmath.structures.MutableBufferFactory +import space.kscience.kmath.structures.indices + +/** + * A class implementing both [DerivativeStructure] and [Symbol]. + */ +@UnstableKMathAPI +public class DerivativeStructureSymbol( + derivativeAlgebra: DerivativeStructureRing, + size: Int, + order: Int, + index: Int, + symbol: Symbol, + value: T, +) : Symbol by symbol, DerivativeStructure( + derivativeAlgebra, + size, + order, + index, + value +) where A : Ring, A : NumericAlgebra, A : ScaleOperations { + override fun toString(): String = symbol.toString() + override fun equals(other: Any?): Boolean = (other as? Symbol) == symbol + override fun hashCode(): Int = symbol.hashCode() +} + +/** + * A ring over [DerivativeStructure]. + * + * @property order The derivation order. + * @param bindings The map of bindings values. All bindings are considered free parameters. + */ +@UnstableKMathAPI +public open class DerivativeStructureRing( + public val algebra: A, + public val bufferFactory: MutableBufferFactory, + public val order: Int, + bindings: Map, +) : Ring>, ScaleOperations>, + NumericAlgebra>, + ExpressionAlgebra>, + NumbersAddOps> where A : Ring, A : NumericAlgebra, A : ScaleOperations { + public val numberOfVariables: Int = bindings.size + + override val zero: DerivativeStructure by lazy { + DerivativeStructure( + this, + numberOfVariables, + order, + ) + } + + override val one: DerivativeStructure by lazy { + DerivativeStructure( + this, + numberOfVariables, + order, + algebra.one, + ) + } + + override fun number(value: Number): DerivativeStructure = const(algebra.number(value)) + + private val variables: Map> = + bindings.entries.mapIndexed { index, (key, value) -> + key to DerivativeStructureSymbol( + this, + numberOfVariables, + order, + index, + key, + value, + ) + }.toMap() + + public override fun const(value: T): DerivativeStructure = + DerivativeStructure(this, numberOfVariables, order, value) + + override fun bindSymbolOrNull(value: String): DerivativeStructureSymbol? = variables[StringSymbol(value)] + + override fun bindSymbol(value: String): DerivativeStructureSymbol = + bindSymbolOrNull(value) ?: error("Symbol '$value' is not supported in $this") + + public fun bindSymbolOrNull(symbol: Symbol): DerivativeStructureSymbol? = variables[symbol.identity] + + public fun bindSymbol(symbol: Symbol): DerivativeStructureSymbol = + bindSymbolOrNull(symbol.identity) ?: error("Symbol '${symbol}' is not supported in $this") + + public fun DerivativeStructure.derivative(symbols: List): T { + require(symbols.size <= order) { "The order of derivative ${symbols.size} exceeds computed order $order" } + val ordersCount = symbols.groupBy { it }.mapValues { it.value.size } + return getPartialDerivative(*variables.keys.map { ordersCount[it] ?: 0 }.toIntArray()) + } + + public fun DerivativeStructure.derivative(vararg symbols: Symbol): T = derivative(symbols.toList()) + + override fun DerivativeStructure.unaryMinus(): DerivativeStructure { + val ds = DerivativeStructure(this@DerivativeStructureRing, compiler) + for (i in ds.data.indices) { + ds.data[i] = algebra { -data[i] } + } + return ds + } + + override fun add(left: DerivativeStructure, right: DerivativeStructure): DerivativeStructure { + left.compiler.checkCompatibility(right.compiler) + val ds = DerivativeStructure(left) + left.compiler.add(left.data, 0, right.data, 0, ds.data, 0) + return ds + } + + override fun scale(a: DerivativeStructure, value: Double): DerivativeStructure { + val ds = DerivativeStructure(a) + for (i in ds.data.indices) { + ds.data[i] = algebra { ds.data[i].times(value) } + } + return ds + } + + override fun multiply( + left: DerivativeStructure, + right: DerivativeStructure + ): DerivativeStructure { + left.compiler.checkCompatibility(right.compiler) + val result = DerivativeStructure(this, left.compiler) + left.compiler.multiply(left.data, 0, right.data, 0, result.data, 0) + return result + } + + override fun DerivativeStructure.minus(arg: DerivativeStructure): DerivativeStructure { + compiler.checkCompatibility(arg.compiler) + val ds = DerivativeStructure(this) + compiler.subtract(data, 0, arg.data, 0, ds.data, 0) + return ds + } + + override operator fun DerivativeStructure.plus(other: Number): DerivativeStructure { + val ds = DerivativeStructure(this) + ds.data[0] = algebra { ds.data[0] + number(other) } + return ds + } + + override operator fun DerivativeStructure.minus(other: Number): DerivativeStructure = + this + -other.toDouble() + + override operator fun Number.plus(other: DerivativeStructure): DerivativeStructure = other + this + override operator fun Number.minus(other: DerivativeStructure): DerivativeStructure = other - this +} + +@UnstableKMathAPI +public class DerivativeStructureRingExpression( + public val algebra: A, + public val bufferFactory: MutableBufferFactory, + public val function: DerivativeStructureRing.() -> DerivativeStructure, +) : DifferentiableExpression where A : Ring, A : ScaleOperations, A : NumericAlgebra { + override operator fun invoke(arguments: Map): T = + DerivativeStructureRing(algebra, bufferFactory, 0, arguments).function().value + + override fun derivativeOrNull(symbols: List): Expression = Expression { arguments -> + with( + DerivativeStructureRing( + algebra, + bufferFactory, + symbols.size, + arguments + ) + ) { function().derivative(symbols) } + } +} + +/** + * A field over commons-math [DerivativeStructure]. + * + * @property order The derivation order. + * @param bindings The map of bindings values. All bindings are considered free parameters. + */ +@UnstableKMathAPI +public class DerivativeStructureField>( + algebra: A, + bufferFactory: MutableBufferFactory, + order: Int, + bindings: Map, +) : DerivativeStructureRing(algebra, bufferFactory, order, bindings), ExtendedField> { + override fun number(value: Number): DerivativeStructure = const(algebra.number(value)) + + override fun divide(left: DerivativeStructure, right: DerivativeStructure): DerivativeStructure { + left.compiler.checkCompatibility(right.compiler) + val result = DerivativeStructure(this, left.compiler) + left.compiler.divide(left.data, 0, right.data, 0, result.data, 0) + return result + } + + override fun sin(arg: DerivativeStructure): DerivativeStructure { + val result = DerivativeStructure(this, arg.compiler) + arg.compiler.sin(arg.data, 0, result.data, 0) + return result + } + + override fun cos(arg: DerivativeStructure): DerivativeStructure { + val result = DerivativeStructure(this, arg.compiler) + arg.compiler.cos(arg.data, 0, result.data, 0) + return result + } + + override fun tan(arg: DerivativeStructure): DerivativeStructure { + val result = DerivativeStructure(this, arg.compiler) + arg.compiler.tan(arg.data, 0, result.data, 0) + return result + } + + override fun asin(arg: DerivativeStructure): DerivativeStructure { + val result = DerivativeStructure(this, arg.compiler) + arg.compiler.asin(arg.data, 0, result.data, 0) + return result + } + + override fun acos(arg: DerivativeStructure): DerivativeStructure { + val result = DerivativeStructure(this, arg.compiler) + arg.compiler.acos(arg.data, 0, result.data, 0) + return result + } + + override fun atan(arg: DerivativeStructure): DerivativeStructure { + val result = DerivativeStructure(this, arg.compiler) + arg.compiler.atan(arg.data, 0, result.data, 0) + return result + } + + override fun sinh(arg: DerivativeStructure): DerivativeStructure { + val result = DerivativeStructure(this, arg.compiler) + arg.compiler.sinh(arg.data, 0, result.data, 0) + return result + } + + override fun cosh(arg: DerivativeStructure): DerivativeStructure { + val result = DerivativeStructure(this, arg.compiler) + arg.compiler.cosh(arg.data, 0, result.data, 0) + return result + } + + override fun tanh(arg: DerivativeStructure): DerivativeStructure { + val result = DerivativeStructure(this, arg.compiler) + arg.compiler.tanh(arg.data, 0, result.data, 0) + return result + } + + override fun asinh(arg: DerivativeStructure): DerivativeStructure { + val result = DerivativeStructure(this, arg.compiler) + arg.compiler.asinh(arg.data, 0, result.data, 0) + return result + } + + override fun acosh(arg: DerivativeStructure): DerivativeStructure { + val result = DerivativeStructure(this, arg.compiler) + arg.compiler.acosh(arg.data, 0, result.data, 0) + return result + } + + override fun atanh(arg: DerivativeStructure): DerivativeStructure { + val result = DerivativeStructure(this, arg.compiler) + arg.compiler.atanh(arg.data, 0, result.data, 0) + return result + } + + override fun power(arg: DerivativeStructure, pow: Number): DerivativeStructure = when (pow) { + is Int -> { + val result = DerivativeStructure(this, arg.compiler) + arg.compiler.pow(arg.data, 0, pow, result.data, 0) + result + } + else -> { + val result = DerivativeStructure(this, arg.compiler) + arg.compiler.pow(arg.data, 0, pow.toDouble(), result.data, 0) + result + } + } + + override fun sqrt(arg: DerivativeStructure): DerivativeStructure { + val result = DerivativeStructure(this, arg.compiler) + arg.compiler.sqrt(arg.data, 0, result.data, 0) + return result + } + + public fun power(arg: DerivativeStructure, pow: DerivativeStructure): DerivativeStructure { + arg.compiler.checkCompatibility(pow.compiler) + val result = DerivativeStructure(this, arg.compiler) + arg.compiler.pow(arg.data, 0, pow.data, 0, result.data, 0) + return result + } + + override fun exp(arg: DerivativeStructure): DerivativeStructure { + val result = DerivativeStructure(this, arg.compiler) + arg.compiler.exp(arg.data, 0, result.data, 0) + return result + } + + override fun ln(arg: DerivativeStructure): DerivativeStructure { + val result = DerivativeStructure(this, arg.compiler) + arg.compiler.ln(arg.data, 0, result.data, 0) + return result + } +} + +@UnstableKMathAPI +public class DerivativeStructureFieldExpression>( + public val algebra: A, + public val bufferFactory: MutableBufferFactory, + public val function: DerivativeStructureField.() -> DerivativeStructure, +) : DifferentiableExpression { + override operator fun invoke(arguments: Map): T = + DerivativeStructureField(algebra, bufferFactory, 0, arguments).function().value + + override fun derivativeOrNull(symbols: List): Expression = Expression { arguments -> + with( + DerivativeStructureField( + algebra, + bufferFactory, + symbols.size, + arguments, + ) + ) { function().derivative(symbols) } + } +} diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpressionTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpressionTest.kt new file mode 100644 index 000000000..429fe310b --- /dev/null +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpressionTest.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + */ + +@file:OptIn(UnstableKMathAPI::class) + +package space.kscience.kmath.expressions + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.structures.DoubleBuffer +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFails + +internal inline fun diff( + order: Int, + vararg parameters: Pair, + block: DerivativeStructureField.() -> Unit, +) { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + DerivativeStructureField(DoubleField, ::DoubleBuffer, order, mapOf(*parameters)).block() +} + +internal class AutoDiffTest { + private val x by symbol + private val y by symbol + + @Test + fun derivativeStructureFieldTest() { + diff(2, x to 1.0, y to 1.0) { + val x = bindSymbol(x)//by binding() + val y = bindSymbol("y") + val z = x * (-sin(x * y) + y) + 2.0 + println(z.derivative(x)) + println(z.derivative(y, x)) + assertEquals(z.derivative(x, y), z.derivative(y, x)) + // check improper order cause failure + assertFails { z.derivative(x, x, y) } + } + } + + @Test + fun autoDifTest() { + val f = DerivativeStructureFieldExpression(DoubleField, ::DoubleBuffer) { + val x by binding + val y by binding + x.pow(2) + 2 * x * y + y.pow(2) + 1 + } + + assertEquals(10.0, f(x to 1.0, y to 2.0)) + assertEquals(6.0, f.derivative(x)(x to 1.0, y to 2.0)) + assertEquals(2.0, f.derivative(x, x)(x to 1.234, y to -2.0)) + assertEquals(2.0, f.derivative(x, y)(x to 1.0, y to 2.0)) + } +} diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalUtils.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalUtils.kt index 3997a77b3..71fd15fe6 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalUtils.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalUtils.kt @@ -48,7 +48,8 @@ internal object InternalUtils { cache.copyInto( logFactorials, BEGIN_LOG_FACTORIALS, - BEGIN_LOG_FACTORIALS, endCopy + BEGIN_LOG_FACTORIALS, + endCopy, ) } else // All values to be computed -- 2.34.1 From 2483c56f1c95180e168bd564be6131122a6c8cfe Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Thu, 3 Mar 2022 20:45:35 +0300 Subject: [PATCH 009/275] Restructured Polynomial --- .../kmath/functions/AbstractPolynomial.kt | 354 +++++++++++++++ .../kscience/kmath/functions/Piecewise.kt | 8 +- .../kscience/kmath/functions/Polynomial.kt | 425 ++++++++++++++---- .../kmath/functions/polynomialUtil.kt | 139 ++++++ .../kmath/integration/SplineIntegrator.kt | 3 +- .../kmath/interpolation/Interpolator.kt | 4 +- .../kmath/functions/PolynomialTest.kt | 11 +- kotlin-js-store/yarn.lock | 56 +-- 8 files changed, 846 insertions(+), 154 deletions(-) create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt new file mode 100644 index 000000000..f6a617656 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt @@ -0,0 +1,354 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.* +import kotlin.js.JsName +import kotlin.jvm.JvmName + + +/** + * Abstraction of polynomials. + */ +public interface AbstractPolynomial + +/** + * Abstraction of ring of polynomials of type [P] over ring of constants of type [C]. + */ +@Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") +public interface AbstractPolynomialSpace> : Ring

{ + // region Constant-integer relation + /** + * Returns sum of the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. + */ + @JvmName("constantIntPlus") + public operator fun C.plus(other: Int): C + /** + * Returns difference between the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. + */ + @JvmName("constantIntMinus") + public operator fun C.minus(other: Int): C + /** + * Returns product of the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + @JvmName("constantIntTimes") + public operator fun C.times(other: Int): C + // endregion + + // region Integer-constant relation + /** + * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. + */ + @JvmName("intConstantPlus") + public operator fun Int.plus(other: C): C + /** + * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. + */ + @JvmName("intConstantMinus") + public operator fun Int.minus(other: C): C + /** + * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + @JvmName("intConstantTimes") + public operator fun Int.times(other: C): C + // endregion + + // region Polynomial-integer relation + /** + * Returns sum of the constant and the integer represented as polynomial. + * + * The operation is equivalent to adding [other] copies of unit polynomial to [this]. + */ + public operator fun P.plus(other: Int): P = optimizedAddMultiplied(this, one, other) + /** + * Returns difference between the constant and the integer represented as polynomial. + * + * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. + */ + public operator fun P.minus(other: Int): P = optimizedAddMultiplied(this, one, -other) + /** + * Returns product of the constant and the integer represented as polynomial. + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + public operator fun P.times(other: Int): P = optimizedMultiply(this, other) + // endregion + + // region Integer-polynomial relation + /** + * Returns sum of the integer represented as polynomial and the constant. + * + * The operation is equivalent to adding [this] copies of unit polynomial to [other]. + */ + public operator fun Int.plus(other: P): P = optimizedAddMultiplied(other, one, this) + /** + * Returns difference between the integer represented as polynomial and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit polynomial from [other]. + */ + public operator fun Int.minus(other: P): P = optimizedAddMultiplied(-other, one, this) + /** + * Returns product of the integer represented as polynomial and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + public operator fun Int.times(other: P): P = optimizedMultiply(other, this) + // endregion + + // region Constant-constant relation + /** + * Returns the same constant. + */ + @JvmName("constantUnaryPlus") + @JsName("constantUnaryPlus") + public operator fun C.unaryPlus(): C = this + /** + * Returns negation of the constant. + */ + @JvmName("constantUnaryMinus") + @JsName("constantUnaryMinus") + public operator fun C.unaryMinus(): C + /** + * Returns sum of the constants. + */ + @JvmName("constantPlus") + @JsName("constantPlus") + public operator fun C.plus(other: C): C + /** + * Returns difference of the constants. + */ + @JvmName("constantMinus") + @JsName("constantMinus") + public operator fun C.minus(other: C): C + /** + * Returns product of the constants. + */ + @JvmName("constantTimes") + @JsName("constantTimes") + public operator fun C.times(other: C): C + + /** + * Check if the instant is zero constant. + */ + @JvmName("constantIsZero") + public fun C.isZero(): Boolean + /** + * Check if the instant is NOT zero constant. + */ + @JvmName("constantIsNotZero") + public fun C.isNotZero(): Boolean + /** + * Check if the instant is unit constant. + */ + @JvmName("constantIsOne") + public fun C.isOne(): Boolean + /** + * Check if the instant is NOT unit constant. + */ + @JvmName("constantIsNotOne") + public fun C.isNotOne(): Boolean + /** + * Check if the instant is minus unit constant. + */ + @JvmName("constantIsMinusOne") + public fun C.isMinusOne(): Boolean + /** + * Check if the instant is NOT minus unit constant. + */ + @JvmName("constantIsNotMinusOne") + public fun C.isNotMinusOne(): Boolean + // endregion + + // region Constant-polynomial relation + /** + * Returns sum of the constant represented as polynomial and the polynomial. + */ + public operator fun C.plus(other: P): P + /** + * Returns difference between the constant represented as polynomial and the polynomial. + */ + public operator fun C.minus(other: P): P + /** + * Returns product of the constant represented as polynomial and the polynomial. + */ + public operator fun C.times(other: P): P + // endregion + + // region Polynomial-constant relation + /** + * Returns sum of the constant represented as polynomial and the polynomial. + */ + public operator fun P.plus(other: C): P + /** + * Returns difference between the constant represented as polynomial and the polynomial. + */ + public operator fun P.minus(other: C): P + /** + * Returns product of the constant represented as polynomial and the polynomial. + */ + public operator fun P.times(other: C): P + // endregion + + // region Polynomial-polynomial relation + /** + * 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 + + /** + * Check if the instant is zero polynomial. + */ + public fun P.isZero(): Boolean = this == zero + /** + * Check if the instant is NOT zero polynomial. + */ + public fun P.isNotZero(): Boolean = this != zero + /** + * Check if the instant is unit polynomial. + */ + public fun P.isOne(): Boolean = this == one + /** + * Check if the instant is NOT unit polynomial. + */ + public fun P.isNotOne(): Boolean = this != one + /** + * Check if the instant is minus unit polynomial. + */ + public fun P.isMinusOne(): Boolean = this == -one + /** + * Check if the instant is NOT minus unit polynomial. + */ + public fun P.isNotMinusOne(): Boolean = this != -one + + /** + * Instance of zero polynomial (zero of the polynomial ring). + */ + override val zero: P + /** + * Instance of unit polynomial (unit of the polynomial ring). + */ + override val one: P + + /** + * Checks equality of the polynomials. + */ + @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") + public fun P.equals(other: P): Boolean + // endregion + + // Not sure is it necessary... + // region Polynomial properties + /** + * 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 + + /** + * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. + */ + public fun P.isConstant(): Boolean = degree <= 0 + /** + * Checks if the instant is **not** constant polynomial (of degree no more than 0) over considered ring. + */ + public fun P.isNotConstant(): Boolean = !isConstant() + /** + * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. + */ + public fun P.isNonZeroConstant(): Boolean = degree == 0 + /** + * Checks if the instant is **not** constant non-zero polynomial (of degree no more than 0) over considered ring. + */ + public fun P.isNotNonZeroConstant(): Boolean = !isNonZeroConstant() + /** + * If polynomial is a constant polynomial represents and returns it as constant. + * Otherwise, (when the polynomial is not constant polynomial) returns `null`. + */ + public fun P.asConstantOrNull(): C? + /** + * If polynomial is a constant polynomial represents and returns it as constant. + * Otherwise, (when the polynomial is not constant polynomial) raises corresponding exception. + */ + public fun P.asConstant(): C = asConstantOrNull() ?: error("Can not represent non-constant polynomial as a constant") + // endregion + + // region Legacy of Ring interface + override fun add(left: P, right: P): P = left + right + override fun multiply(left: P, right: P): P = left * right + // endregion + + public companion object { + // TODO: All of this should be moved to algebraic structures' place for utilities + // TODO: Move receiver to context receiver + /** + * Multiplication of element and integer. + * + * @receiver the multiplicand. + * @param other the multiplier. + * @return the difference. + */ + internal tailrec fun Group.optimizedMultiply(arg: C, other: Int): C = + when { + other == 0 -> zero + other == 1 -> arg + other == -1 -> -arg + other % 2 == 0 -> optimizedMultiply(arg + arg, other / 2) + other % 2 == 1 -> optimizedAddMultiplied(arg, arg + arg, other / 2) + other % 2 == -1 -> optimizedAddMultiplied(-arg, arg + arg, other / 2) + else -> error("Error in multiplication group instant by integer: got reminder by division by 2 different from 0, 1 and -1") + } + + // TODO: Move receiver to context receiver + /** + * Adds product of [arg] and [multiplier] to [base]. + * + * @receiver the algebra to provide multiplication. + * @param base the augend. + * @param arg the multiplicand. + * @param multiplier the multiplier. + * @return sum of the augend [base] and product of the multiplicand [arg] and the multiplier [multiplier]. + * @author Gleb Minaev + */ + internal tailrec fun Group.optimizedAddMultiplied(base: C, arg: C, multiplier: Int): C = + when { + multiplier == 0 -> base + multiplier == 1 -> base + arg + multiplier == -1 -> base - arg + multiplier % 2 == 0 -> optimizedAddMultiplied(base, arg + arg, multiplier / 2) + multiplier % 2 == 1 -> optimizedAddMultiplied(base + arg, arg + arg, multiplier / 2) + multiplier % 2 == -1 -> optimizedAddMultiplied(base + arg, arg + arg, multiplier / 2) + else -> error("Error in multiplication group instant by integer: got reminder by division by 2 different from 0, 1 and -1") + } + } +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt index 16af7f555..cfd21d552 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt @@ -117,16 +117,16 @@ public fun > PiecewisePolynomial( * Return a value of polynomial function with given [ring] a given [arg] or null if argument is outside piecewise * definition. */ -public fun , C : Ring> PiecewisePolynomial.value(ring: C, arg: T): T? = - findPiece(arg)?.value(ring, arg) +public fun , C : Ring> PiecewisePolynomial.substitute(ring: C, arg: T): T? = + findPiece(arg)?.substitute(ring, arg) /** * Convert this polynomial to a function returning nullable value (null if argument is outside piecewise range). */ -public fun , C : Ring> PiecewisePolynomial.asFunction(ring: C): (T) -> T? = { value(ring, it) } +public fun , C : Ring> PiecewisePolynomial.asFunction(ring: C): (T) -> T? = { substitute(ring, it) } /** * Convert this polynomial to a function using [defaultValue] for arguments outside the piecewise range. */ public fun , C : Ring> PiecewisePolynomial.asFunction(ring: C, defaultValue: T): (T) -> T = - { value(ring, it) ?: defaultValue } + { substitute(ring, it) ?: defaultValue } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index a36d36f52..30280a396 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -5,128 +5,371 @@ package space.kscience.kmath.functions -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.functions.AbstractPolynomialSpace.Companion.optimizedAddMultiplied +import space.kscience.kmath.functions.AbstractPolynomialSpace.Companion.optimizedMultiply import space.kscience.kmath.operations.* -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract +import kotlin.jvm.JvmName import kotlin.math.max -import kotlin.math.pow +import kotlin.math.min /** * Polynomial coefficients model without fixation on specific context they are applied to. * * @param coefficients constant is the leftmost coefficient. */ -public class Polynomial(public val coefficients: List) { +public class Polynomial(public val coefficients: List) : AbstractPolynomial { override fun toString(): String = "Polynomial$coefficients" + +// public companion object { +// /** +// * Default name of variables used in string representations. +// * +// * @see Polynomial.toString +// */ +// public var defaultVariableName: String = "x" +// +// /** +// * Represents result of division with remainder. +// */ +// public data class DividingResult( +// val quotient: Polynomial, +// val reminder: Polynomial +// ) +// } } /** - * Returns a [Polynomial] instance with given [coefficients]. + * Represents internal [Polynomial] errors. + */ +internal class PolynomialError(message: String): Error(message) + +// region Constructors and converters + +/** + * Returns a [Polynomial] instance with given [coefficients]. The collection of coefficients will be reversed if + * [reverse] parameter is true. */ @Suppress("FunctionName") -public fun Polynomial(vararg coefficients: T): Polynomial = Polynomial(coefficients.toList()) +public fun Polynomial(coefficients: List, reverse: Boolean = false): Polynomial = + Polynomial(with(coefficients) { if (reverse) reversed() else this }) /** - * Evaluates the value of the given double polynomial for given double argument. + * Returns a [Polynomial] instance with given [coefficients]. The collection of coefficients will be reversed if + * [reverse] parameter is true. */ -public fun Polynomial.value(arg: Double): Double = coefficients.reduceIndexed { index, acc, c -> - acc + c * arg.pow(index) -} +@Suppress("FunctionName") +public fun Polynomial(vararg coefficients: T, reverse: Boolean = false): Polynomial = + Polynomial(with(coefficients) { if (reverse) reversed() else toList() }) + +public fun T.asPolynomial() : Polynomial = Polynomial(listOf(this)) + +// endregion /** - * Evaluates the value of the given polynomial for given argument. - * https://en.wikipedia.org/wiki/Horner%27s_method - */ -public fun > Polynomial.value(ring: C, arg: T): T = ring { - if (coefficients.isEmpty()) return@ring zero - var result: T = coefficients.last() - for (j in coefficients.size - 2 downTo 0) { - result = (arg * result) + coefficients[j] - } - return result -} - -/** - * Represent the polynomial as a regular context-less function. - */ -public fun > Polynomial.asFunction(ring: C): (T) -> T = { value(ring, it) } - -/** - * Create a polynomial witch represents differentiated version of this polynomial - */ -@UnstableKMathAPI -public fun Polynomial.differentiate( - algebra: A, -): Polynomial where A : Ring, A : NumericAlgebra = algebra { - Polynomial(coefficients.drop(1).mapIndexed { index, t -> number(index) * t }) -} - -/** - * Create a polynomial witch represents indefinite integral version of this polynomial - */ -@UnstableKMathAPI -public fun Polynomial.integrate( - algebra: A, -): Polynomial where A : Field, A : NumericAlgebra = algebra { - val integratedCoefficients = buildList(coefficients.size + 1) { - add(zero) - coefficients.forEachIndexed{ index, t -> add(t / (number(index) + one)) } - } - Polynomial(integratedCoefficients) -} - -/** - * Compute a definite integral of a given polynomial in a [range] - */ -@UnstableKMathAPI -public fun > Polynomial.integrate( - algebra: Field, - range: ClosedRange, -): T = algebra { - val integral = integrate(algebra) - integral.value(algebra, range.endInclusive) - integral.value(algebra, range.start) -} - -/** - * Space of polynomials. + * Space of polynomials constructed over ring. * - * @param T the type of operated polynomials. - * @param C the intersection of [Ring] of [T] and [ScaleOperations] of [T]. - * @param ring the [C] instance. + * @param C the type of constants. Polynomials have them 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 PolynomialSpace( - private val ring: C, -) : Group>, ScaleOperations> where C : Ring, C : ScaleOperations { - override val zero: Polynomial = Polynomial(emptyList()) +@Suppress("INAPPLICABLE_JVM_NAME") // KT-31420 +public open class PolynomialSpace>( + public val ring: A, +) : AbstractPolynomialSpace>{ + // region Constant-integer relation + @JvmName("constantIntPlus") + public override operator fun C.plus(other: Int): C = ring { optimizedAddMultiplied(this@plus, one, other) } + @JvmName("constantIntMinus") + public override operator fun C.minus(other: Int): C = ring { optimizedAddMultiplied(this@minus, one, -other) } + @JvmName("constantIntTimes") + public override operator fun C.times(other: Int): C = ring { optimizedMultiply(this@times, other) } + // endregion - override fun Polynomial.unaryMinus(): Polynomial = ring { + // region Integer-constant relation + @JvmName("intConstantPlus") + public override operator fun Int.plus(other: C): C = ring { optimizedAddMultiplied(other, one, this@plus) } + @JvmName("intConstantMinus") + public override operator fun Int.minus(other: C): C = ring { optimizedAddMultiplied(-other, one, this@minus) } + @JvmName("intConstantTimes") + public override operator fun Int.times(other: C): C = ring { optimizedMultiply(other, this@times) } + // endregion + + // region Polynomial-integer relation + public override operator fun Polynomial.plus(other: Int): Polynomial = + if (other == 0) this + else + Polynomial( + coefficients + .toMutableList() + .apply { + if (isEmpty()) this[0] = ring.zero + other + else this[0] = this[0]!! + other + } + ) + public override operator fun Polynomial.minus(other: Int): Polynomial = + if (other == 0) this + else + Polynomial( + coefficients + .toMutableList() + .apply { + if (isEmpty()) this[0] = ring.zero - other + else this[0] = this[0]!! - other + } + ) + public override operator fun Polynomial.times(other: Int): Polynomial = + if (other == 0) zero + else Polynomial( + coefficients + .subList(0, degree + 1) + .map { it * other } + ) + // endregion + + // region Integer-polynomial relation + public override operator fun Int.plus(other: Polynomial): Polynomial = + if (this == 0) other + else + Polynomial( + other.coefficients + .toMutableList() + .apply { + if (isEmpty()) this[0] = ring.zero + this@plus + else this[0] = this[0]!! + this@plus + } + ) + public override operator fun Int.minus(other: Polynomial): Polynomial = + if (this == 0) other + else + Polynomial( + other.coefficients + .toMutableList() + .apply { + if (isEmpty()) this[0] = ring.zero - this@minus + else this[0] = this[0]!! - this@minus + } + ) + public override operator fun Int.times(other: Polynomial): Polynomial = + if (this == 0) zero + else Polynomial( + other.coefficients + .subList(0, other.degree + 1) + .map { it * this } + ) + // endregion + + // region Constant-constant relation + @JvmName("constantUnaryMinus") + public override operator fun C.unaryMinus(): C = ring { -this@unaryMinus } + @JvmName("constantPlus") + public override operator fun C.plus(other: C): C = ring { this@plus + other } + @JvmName("constantMinus") + public override operator fun C.minus(other: C): C = ring { this@minus - other } + @JvmName("constantTimes") + public override operator fun C.times(other: C): C = ring { this@times * other } + @JvmName("constantIsZero") + public override fun C.isZero(): Boolean = ring { this == zero } + @JvmName("constantIsNotZero") + public override fun C.isNotZero(): Boolean = ring { this != zero } + @JvmName("constantIsOne") + public override fun C.isOne(): Boolean = ring { this == one } + @JvmName("constantIsNotOne") + public override fun C.isNotOne(): Boolean = ring { this != one } + @JvmName("constantIsMinusOne") + public override fun C.isMinusOne(): Boolean = ring { this == -one } + @JvmName("constantIsNotMinusOne") + public override fun C.isNotMinusOne(): Boolean = ring { this != -one } + // endregion + + // region Constant-polynomial relation + public override operator fun C.plus(other: Polynomial): Polynomial = + with(other.coefficients) { + if (isEmpty()) Polynomial(listOf(this@plus)) + else Polynomial( + toMutableList() + .apply { + this[0] += this@plus + } + ) + } +// if (degree == -1) UnivariatePolynomial(other) else UnivariatePolynomial( +// listOf(coefficients[0] + other) + coefficients.subList(1, degree + 1) +// ) + public override operator fun C.minus(other: Polynomial): Polynomial = + with(other.coefficients) { + if (isEmpty()) Polynomial(listOf(-this@minus)) + else Polynomial( + toMutableList() + .apply { + this[0] -= this@minus + } + ) + } +// if (degree == -1) UnivariatePolynomial(other) else UnivariatePolynomial( +// listOf(coefficients[0] + other) + coefficients.subList(1, degree + 1) +// ) + public override operator fun C.times(other: Polynomial): Polynomial = + Polynomial( + other.coefficients +// .subList(0, other.degree + 1) + .map { it * this } + ) + // endregion + + // region Polynomial-constant relation + public override operator fun Polynomial.plus(other: C): Polynomial = + if (other.isZero()) this + else with(coefficients) { + if (isEmpty()) Polynomial(listOf(other)) + else Polynomial( + toMutableList() + .apply { + this[0] += other + } + ) + } +// if (degree == -1) UnivariatePolynomial(other) else UnivariatePolynomial( +// listOf(coefficients[0] + other) + coefficients.subList(1, degree + 1) +// ) + public override operator fun Polynomial.minus(other: C): Polynomial = + with(coefficients) { + if (isEmpty()) Polynomial(listOf(other)) + else Polynomial( + toMutableList() + .apply { + this[0] -= other + } + ) + } +// if (degree == -1) UnivariatePolynomial(-other) else UnivariatePolynomial( +// listOf(coefficients[0] - other) + coefficients.subList(1, degree + 1) +// ) + public override operator fun Polynomial.times(other: C): Polynomial = + Polynomial( + coefficients +// .subList(0, degree + 1) + .map { it * other } + ) + // endregion + + // region Polynomial-polynomial relation + public override operator fun Polynomial.unaryMinus(): Polynomial = Polynomial(coefficients.map { -it }) - } - - override fun add(left: Polynomial, right: Polynomial): Polynomial { - val dim = max(left.coefficients.size, right.coefficients.size) - - return ring { - Polynomial(List(dim) { index -> - left.coefficients.getOrElse(index) { zero } + right.coefficients.getOrElse(index) { zero } - }) + public override operator fun Polynomial.plus(other: Polynomial): Polynomial = + Polynomial( + (0..max(degree, other.degree)) + .map { + when { + it > degree -> other.coefficients[it] + it > other.degree -> coefficients[it] + else -> coefficients[it] + other.coefficients[it] + } + } + .ifEmpty { listOf(ring.zero) } + ) + public override operator fun Polynomial.minus(other: Polynomial): Polynomial = + Polynomial( + (0..max(degree, other.degree)) + .map { + when { + it > degree -> -other.coefficients[it] + it > other.degree -> coefficients[it] + else -> coefficients[it] - other.coefficients[it] + } + } + .ifEmpty { listOf(ring.zero) } + ) + public override operator fun Polynomial.times(other: Polynomial): Polynomial { + val thisDegree = degree + val otherDegree = other.degree + return when { + thisDegree == -1 -> this + otherDegree == -1 -> other + else -> + Polynomial( + (0..(thisDegree + otherDegree)) + .map { d -> + (max(0, d - otherDegree)..(min(thisDegree, d))) + .map { coefficients[it] * other.coefficients[d - it] } + .reduce { acc, rational -> acc + rational } + } + ) } } - override fun scale(a: Polynomial, value: Double): Polynomial = - ring { Polynomial(List(a.coefficients.size) { index -> a.coefficients[index] * value }) } + public override fun Polynomial.isZero(): Boolean = coefficients.all { it.isZero() } + public override fun Polynomial.isNotZero(): Boolean = coefficients.any { it.isNotZero() } + public override fun Polynomial.isOne(): Boolean = + with(coefficients) { isNotEmpty() && asSequence().withIndex().any { (index, c) -> if (index == 0) c.isOne() else c.isZero() } } // TODO: It's better to write new methods like `anyIndexed`. But what's better way to do it? + public override fun Polynomial.isNotOne(): Boolean = !isOne() + public override fun Polynomial.isMinusOne(): Boolean = + with(coefficients) { isNotEmpty() && asSequence().withIndex().any { (index, c) -> if (index == 0) c.isMinusOne() else c.isZero() } } // TODO: It's better to write new methods like `anyIndexed`. But what's better way to do it? + public override fun Polynomial.isNotMinusOne(): Boolean = !isMinusOne() + + override val zero: Polynomial = Polynomial(emptyList()) + override val one: Polynomial = Polynomial(listOf(ring.one)) + + @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") + public override fun Polynomial.equals(other: Polynomial): Boolean = + when { + this === other -> true + else -> { + if (this.degree == other.degree) + (0..degree).all { coefficients[it] == other.coefficients[it] } + else false + } + } + // endregion + + // Not sure is it necessary... + // region Polynomial properties + public override val Polynomial.degree: Int get() = coefficients.indexOfLast { it != ring.zero } + + public override fun Polynomial.asConstantOrNull(): C? = + with(coefficients) { + when { + isEmpty() -> ring.zero + degree > 0 -> null + else -> first() + } + } + public override fun Polynomial.asConstant(): C = asConstantOrNull() ?: error("Can not represent non-constant polynomial as a constant") + + @Suppress("NOTHING_TO_INLINE") + public inline fun Polynomial.substitute(argument: C): C = this.substitute(ring, argument) + @Suppress("NOTHING_TO_INLINE") + public inline fun Polynomial.substitute(argument: Polynomial): Polynomial = this.substitute(ring, argument) + + @Suppress("NOTHING_TO_INLINE") + public inline fun Polynomial.asFunction(): (C) -> C = { this.substitute(ring, it) } + @Suppress("NOTHING_TO_INLINE") + public inline fun Polynomial.asFunctionOnConstants(): (C) -> C = { this.substitute(ring, it) } + @Suppress("NOTHING_TO_INLINE") + public inline fun Polynomial.asFunctionOnPolynomials(): (Polynomial) -> Polynomial = { this.substitute(ring, it) } /** * Evaluates the polynomial for the given value [arg]. */ - public operator fun Polynomial.invoke(arg: T): T = value(ring, arg) - - public fun Polynomial.asFunction(): (T) -> T = asFunction(ring) + @Suppress("NOTHING_TO_INLINE") + public inline operator fun Polynomial.invoke(argument: C): C = this.substitute(ring, argument) + @Suppress("NOTHING_TO_INLINE") + public inline operator fun Polynomial.invoke(argument: Polynomial): Polynomial = this.substitute(ring, argument) + // endregion } -public inline fun C.polynomial(block: PolynomialSpace.() -> R): R where C : Ring, C : ScaleOperations { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return PolynomialSpace(this).block() +/** + * 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 ScalablePolynomialSpace( + ring: A, +) : PolynomialSpace(ring), ScaleOperations> where A : Ring, A : ScaleOperations { + + override fun scale(a: Polynomial, value: Double): Polynomial = + ring { Polynomial(List(a.coefficients.size) { index -> a.coefficients[index] * value }) } + } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt new file mode 100644 index 000000000..1a3eb7874 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt @@ -0,0 +1,139 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.* +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract +import kotlin.jvm.JvmName +import kotlin.math.pow + + +// region Utilities + +/** + * Removes zeros on the end of the coefficient list of polynomial. + */ +//context(PolynomialSpace) +//fun > Polynomial.removeZeros() : Polynomial = +// if (degree > -1) Polynomial(coefficients.subList(0, degree + 1)) else zero + +/** + * Crates a [PolynomialSpace] over received ring. + */ +public fun > A.polynomial(): PolynomialSpace = + PolynomialSpace(this) + +/** + * Crates a [PolynomialSpace]'s scope over received ring. + */ +public inline fun , R> A.polynomial(block: PolynomialSpace.() -> R): R { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return PolynomialSpace(this).block() +} + +/** + * Crates a [ScalablePolynomialSpace] over received scalable ring. + */ +public fun A.scalablePolynomial(): ScalablePolynomialSpace where A : Ring, A : ScaleOperations = + ScalablePolynomialSpace(this) + +/** + * Crates a [ScalablePolynomialSpace]'s scope over received scalable ring. + */ +public inline fun A.scalablePolynomial(block: ScalablePolynomialSpace.() -> R): R where A : Ring, A : ScaleOperations { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return ScalablePolynomialSpace(this).block() +} + +// endregion + +// region Polynomial substitution and functional representation + +// TODO: May be apply Horner's method too? +/** + * Evaluates the value of the given double polynomial for given double argument. + */ +public fun Polynomial.substitute(arg: Double): Double = + coefficients.reduceIndexedOrNull { index, acc, c -> + acc + c * arg.pow(index) + } ?: .0 + +/** + * Evaluates the value of the given polynomial for given argument. + * + * It is an implementation of [Horner's method](https://en.wikipedia.org/wiki/Horner%27s_method). + */ +public fun Polynomial.substitute(ring: Ring, arg: C): C = ring { + if (coefficients.isEmpty()) return@ring zero + var result: C = coefficients.last() + for (j in coefficients.size - 2 downTo 0) { + result = (arg * result) + coefficients[j] + } + return result +} + +// TODO: (Waiting for hero) Replace with optimisation: the [result] may be unboxed, and all operations may be performed +// as soon as possible on it +public fun Polynomial.substitute(ring: Ring, arg: Polynomial) : Polynomial = ring.polynomial { + if (coefficients.isEmpty()) return zero + var result: Polynomial = coefficients.last().asPolynomial() + for (j in coefficients.size - 2 downTo 0) { + result = (arg * result) + coefficients[j] + } + return result +} + +/** + * Represent the polynomial as a regular context-less function. + */ +public fun > Polynomial.asFunction(ring: A): (C) -> C = { substitute(ring, it) } + +/** + * Represent the polynomial as a regular context-less function. + */ +public fun > Polynomial.asPolynomialFunctionOver(ring: A): (Polynomial) -> Polynomial = { substitute(ring, it) } + +// endregion + +// region Algebraic derivative and antiderivative + +/** + * Returns algebraic derivative of received polynomial. + */ +@UnstableKMathAPI +public fun Polynomial.derivative( + algebra: A, +): Polynomial where A : Ring, A : NumericAlgebra = algebra { + Polynomial(coefficients.drop(1).mapIndexed { index, t -> number(index) * t }) +} + +/** + * Create a polynomial witch represents indefinite integral version of this polynomial + */ +@UnstableKMathAPI +public fun Polynomial.antiderivative( + algebra: A, +): Polynomial where A : Field, A : NumericAlgebra = algebra { + val integratedCoefficients = buildList(coefficients.size + 1) { + add(zero) + coefficients.forEachIndexed{ index, t -> add(t / (number(index) + one)) } + } + Polynomial(integratedCoefficients) +} + +/** + * Compute a definite integral of a given polynomial in a [range] + */ +@UnstableKMathAPI +public fun > Polynomial.integrate( + algebra: Field, + range: ClosedRange, +): C = algebra { + val integral = antiderivative(algebra) + integral.substitute(algebra, range.endInclusive) - integral.substitute(algebra, range.start) +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt index 15d548641..2e6873ece 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 @@ -7,6 +7,7 @@ package space.kscience.kmath.integration import space.kscience.kmath.functions.PiecewisePolynomial import space.kscience.kmath.functions.integrate +import space.kscience.kmath.functions.antiderivative import space.kscience.kmath.interpolation.PolynomialInterpolator import space.kscience.kmath.interpolation.SplineInterpolator import space.kscience.kmath.interpolation.interpolatePolynomials @@ -23,7 +24,7 @@ import space.kscience.kmath.structures.MutableBufferFactory @OptIn(PerformancePitfall::class) @UnstableKMathAPI public fun > PiecewisePolynomial.integrate(algebra: Field): PiecewisePolynomial = - PiecewisePolynomial(pieces.map { it.first to it.second.integrate(algebra) }) + PiecewisePolynomial(pieces.map { it.first to it.second.antiderivative(algebra) }) /** * Compute definite integral of given [PiecewisePolynomial] piece by piece in a given [range] diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt index b13adefa5..bbd76c87e 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt @@ -9,7 +9,7 @@ package space.kscience.kmath.interpolation import space.kscience.kmath.data.XYColumnarData import space.kscience.kmath.functions.PiecewisePolynomial -import space.kscience.kmath.functions.value +import space.kscience.kmath.functions.substitute import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Ring import space.kscience.kmath.structures.Buffer @@ -33,7 +33,7 @@ public interface PolynomialInterpolator> : Interpolator): PiecewisePolynomial override fun interpolate(points: XYColumnarData): (T) -> T = { x -> - interpolatePolynomials(points).value(algebra, x) ?: getDefaultValue() + interpolatePolynomials(points).substitute(algebra, x) ?: getDefaultValue() } } diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt index 05c16d17e..e0f0e32a4 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt @@ -5,13 +5,22 @@ package space.kscience.kmath.functions +import space.kscience.kmath.operations.algebra import kotlin.test.Test import kotlin.test.assertEquals class PolynomialTest { + @Test + fun simple_polynomial_test() { + Double.algebra.scalablePolynomial { + val x = Polynomial(listOf(0.0, 1.0)) + val polynomial = x * x - 2 * x + 1 + assertEquals(0.0, polynomial.substitute(1.0), 0.001) + } + } @Test fun testIntegration() { val polynomial = Polynomial(1.0, -2.0, 1.0) - assertEquals(0.0, polynomial.value(1.0), 0.001) + assertEquals(0.0, polynomial.substitute(1.0), 0.001) } } \ No newline at end of file diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock index e21abe604..9fc75720e 100644 --- a/kotlin-js-store/yarn.lock +++ b/kotlin-js-store/yarn.lock @@ -274,11 +274,6 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -astring@1.7.5: - version "1.7.5" - resolved "https://registry.yarnpkg.com/astring/-/astring-1.7.5.tgz#a7d47fceaf32b052d33a3d07c511efeec67447ca" - integrity sha512-lobf6RWXb8c4uZ7Mdq0U12efYmpD1UFnyOWVJPTa3ukqZrMopav+2hdNu0hgBF0JIBFK9QgrBDfwYvh3DFJDAA== - balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -294,24 +289,11 @@ base64id@2.0.0, base64id@~2.0.0: resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== -benchmark@*: - version "2.1.4" - resolved "https://registry.yarnpkg.com/benchmark/-/benchmark-2.1.4.tgz#09f3de31c916425d498cc2ee565a0ebf3c2a5629" - integrity sha1-CfPeMckWQl1JjMLuVloOvzwqVik= - dependencies: - lodash "^4.17.4" - platform "^1.3.3" - binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== -binaryen@101.0.0: - version "101.0.0" - resolved "https://registry.yarnpkg.com/binaryen/-/binaryen-101.0.0.tgz#42a9e4cc7a22e2c1d75a31d28005a9b518b2c555" - integrity sha512-FRmVxvrR8jtcf0qcukNAPZDM3dZ2sc9GmA/hKxBI7k3fFzREKh1cAs+ruQi+ITTKz7u/AuFMuVnbJwTh0ef/HQ== - body-parser@^1.19.0: version "1.19.1" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.1.tgz#1499abbaa9274af3ecc9f6f10396c995943e31d4" @@ -599,14 +581,6 @@ dom-serialize@^2.2.1: extend "^3.0.0" void-elements "^2.0.0" -dukat@0.5.8-rc.4: - version "0.5.8-rc.4" - resolved "https://registry.yarnpkg.com/dukat/-/dukat-0.5.8-rc.4.tgz#90384dcb50b14c26f0e99dae92b2dea44f5fce21" - integrity sha512-ZnMt6DGBjlVgK2uQamXfd7uP/AxH7RqI0BL9GLrrJb2gKdDxvJChWy+M9AQEaL+7/6TmxzJxFOsRiInY9oGWTA== - dependencies: - google-protobuf "3.12.2" - typescript "3.9.5" - ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -881,11 +855,6 @@ glob@^7.1.3, glob@^7.1.7: once "^1.3.0" path-is-absolute "^1.0.0" -google-protobuf@3.12.2: - version "3.12.2" - resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.12.2.tgz#50ce9f9b6281235724eb243d6a83e969a2176e53" - integrity sha512-4CZhpuRr1d6HjlyrxoXoocoGFnRYgKULgMtikMddA9ztRyYR59Aondv2FioyxWVamRo0rF2XpYawkTCBEQOSkA== - graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6: version "4.2.9" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" @@ -1065,11 +1034,6 @@ jest-worker@^27.4.1: merge-stream "^2.0.0" supports-color "^8.0.0" -js-base64@3.6.1: - version "3.6.1" - resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.6.1.tgz#555aae398b74694b4037af1f8a5a6209d170efbe" - integrity sha512-Frdq2+tRRGLQUIQOgsIGSCd1VePCS2fsddTG5dTCqR0JHgltXWfsxnY0gIXPoMeRmdom6Oyq+UMOFg5suduOjQ== - js-yaml@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" @@ -1179,7 +1143,7 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" -lodash@^4.17.15, lodash@^4.17.21, lodash@^4.17.4: +lodash@^4.17.15, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -1437,11 +1401,6 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -platform@^1.3.3: - version "1.3.6" - resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.6.tgz#48b4ce983164b209c2d45a107adb31f473a6e7a7" - integrity sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg== - postcss-modules-extract-imports@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" @@ -1696,14 +1655,6 @@ source-map-loader@3.0.0: iconv-lite "^0.6.2" source-map-js "^0.6.2" -source-map-support@0.5.20: - version "0.5.20" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9" - integrity sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" @@ -1838,11 +1789,6 @@ type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" -typescript@3.9.5: - version "3.9.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.5.tgz#586f0dba300cde8be52dd1ac4f7e1009c1b13f36" - integrity sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ== - ua-parser-js@^0.7.28: version "0.7.31" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.31.tgz#649a656b191dffab4f21d5e053e27ca17cbff5c6" -- 2.34.1 From ab9dcd83b90a468a325948a1c32257ae0a5d5875 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Thu, 10 Mar 2022 01:44:14 +0300 Subject: [PATCH 010/275] Added abstract rational functions --- .../kmath/functions/AbstractPolynomial.kt | 16 +- .../functions/AbstractRationalFunction.kt | 507 ++++++++++++++++++ 2 files changed, 515 insertions(+), 8 deletions(-) create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt index f6a617656..237a72bcc 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt @@ -70,19 +70,19 @@ public interface AbstractPolynomialSpace> : Ring

// region Polynomial-integer relation /** - * Returns sum of the constant and the integer represented as polynomial. + * Returns sum of the polynomial and the integer represented as polynomial. * * The operation is equivalent to adding [other] copies of unit polynomial to [this]. */ public operator fun P.plus(other: Int): P = optimizedAddMultiplied(this, one, other) /** - * Returns difference between the constant and the integer represented as polynomial. + * Returns difference between the polynomial and the integer represented as polynomial. * * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. */ public operator fun P.minus(other: Int): P = optimizedAddMultiplied(this, one, -other) /** - * Returns product of the constant and the integer represented as polynomial. + * Returns product of the polynomial and the integer represented as polynomial. * * The operation is equivalent to sum of [other] copies of [this]. */ @@ -91,19 +91,19 @@ public interface AbstractPolynomialSpace> : Ring

// region Integer-polynomial relation /** - * Returns sum of the integer represented as polynomial and the constant. + * Returns sum of the integer represented as 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 = optimizedAddMultiplied(other, one, this) /** - * Returns difference between the integer represented as polynomial and the constant. + * Returns difference between the integer represented as 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 = optimizedAddMultiplied(-other, one, this) /** - * Returns product of the integer represented as polynomial and the constant. + * Returns product of the integer represented as polynomial and the polynomial. * * The operation is equivalent to sum of [this] copies of [other]. */ @@ -254,11 +254,11 @@ public interface AbstractPolynomialSpace> : Ring

/** * Instance of zero polynomial (zero of the polynomial ring). */ - override val zero: P + public override val zero: P /** * Instance of unit polynomial (unit of the polynomial ring). */ - override val one: P + public override val one: P /** * Checks equality of the polynomials. diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt new file mode 100644 index 000000000..5cb570c9f --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt @@ -0,0 +1,507 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.functions.AbstractPolynomialSpace.Companion.optimizedAddMultiplied +import space.kscience.kmath.functions.AbstractPolynomialSpace.Companion.optimizedMultiply +import space.kscience.kmath.operations.* +import kotlin.js.JsName +import kotlin.jvm.JvmName + + +/** + * Abstraction of rational function. + */ +public interface AbstractRationalFunction> + +@Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") +public interface AbstractRationalFunctionalSpace, R: AbstractRationalFunction> : Ring { + // region Constant-integer relation + /** + * Returns sum of the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. + */ + @JvmName("constantIntPlus") + public operator fun C.plus(other: Int): C + /** + * Returns difference between the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. + */ + @JvmName("constantIntMinus") + public operator fun C.minus(other: Int): C + /** + * Returns product of the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + @JvmName("constantIntTimes") + public operator fun C.times(other: Int): C + // endregion + + // region Integer-constant relation + /** + * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. + */ + @JvmName("intConstantPlus") + public operator fun Int.plus(other: C): C + /** + * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. + */ + @JvmName("intConstantMinus") + public operator fun Int.minus(other: C): C + /** + * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + @JvmName("intConstantTimes") + public operator fun Int.times(other: C): C + // endregion + + // region Polynomial-integer relation + /** + * Returns sum of the constant and the integer represented as polynomial. + * + * The operation is equivalent to adding [other] copies of unit polynomial to [this]. + */ + public operator fun P.plus(other: Int): P + /** + * Returns difference between the constant and the integer represented as polynomial. + * + * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. + */ + public operator fun P.minus(other: Int): P + /** + * Returns product of the constant and the integer represented as polynomial. + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + public operator fun P.times(other: Int): P + // endregion + + // region Integer-polynomial relation + /** + * Returns sum of the integer represented as polynomial and the constant. + * + * The operation is equivalent to adding [this] copies of unit polynomial to [other]. + */ + public operator fun Int.plus(other: P): P + /** + * Returns difference between the integer represented as polynomial and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit polynomial from [other]. + */ + public operator fun Int.minus(other: P): P + /** + * Returns product of the integer represented as polynomial and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + public operator fun Int.times(other: P): P + // endregion + + // region Rational-integer relation + /** + * Returns sum of the rational function and the integer represented as rational function. + * + * The operation is equivalent to adding [other] copies of unit polynomial to [this]. + */ + public operator fun R.plus(other: Int): R = optimizedAddMultiplied(this, one, other) + /** + * Returns difference between the rational function and the integer represented as rational function. + * + * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. + */ + public operator fun R.minus(other: Int): R = optimizedAddMultiplied(this, one, -other) + /** + * Returns product of the rational function and the integer represented as rational function. + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + public operator fun R.times(other: Int): R = optimizedMultiply(this, other) + // endregion + + // region Integer-Rational relation + /** + * Returns sum of the integer represented as 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 = optimizedAddMultiplied(other, one, this) + /** + * Returns difference between the integer represented as 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 = optimizedAddMultiplied(-other, one, this) + /** + * Returns product of the integer represented as 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 = optimizedMultiply(other, this) + // endregion + + // region Constant-constant relation + /** + * Returns the same constant. + */ + @JvmName("constantUnaryPlus") + @JsName("constantUnaryPlus") + public operator fun C.unaryPlus(): C = this + /** + * Returns negation of the constant. + */ + @JvmName("constantUnaryMinus") + @JsName("constantUnaryMinus") + public operator fun C.unaryMinus(): C + /** + * Returns sum of the constants. + */ + @JvmName("constantPlus") + @JsName("constantPlus") + public operator fun C.plus(other: C): C + /** + * Returns difference of the constants. + */ + @JvmName("constantMinus") + @JsName("constantMinus") + public operator fun C.minus(other: C): C + /** + * Returns product of the constants. + */ + @JvmName("constantTimes") + @JsName("constantTimes") + public operator fun C.times(other: C): C + + /** + * Check if the instant is zero constant. + */ + @JvmName("constantIsZero") + public fun C.isZero(): Boolean + /** + * Check if the instant is NOT zero constant. + */ + @JvmName("constantIsNotZero") + public fun C.isNotZero(): Boolean + /** + * Check if the instant is unit constant. + */ + @JvmName("constantIsOne") + public fun C.isOne(): Boolean + /** + * Check if the instant is NOT unit constant. + */ + @JvmName("constantIsNotOne") + public fun C.isNotOne(): Boolean + /** + * Check if the instant is minus unit constant. + */ + @JvmName("constantIsMinusOne") + public fun C.isMinusOne(): Boolean + /** + * Check if the instant is NOT minus unit constant. + */ + @JvmName("constantIsNotMinusOne") + public fun C.isNotMinusOne(): Boolean + // endregion + + // region Constant-polynomial relation + /** + * Returns sum of the constant represented as polynomial and the polynomial. + */ + public operator fun C.plus(other: P): P + /** + * Returns difference between the constant represented as polynomial and the polynomial. + */ + public operator fun C.minus(other: P): P + /** + * Returns product of the constant represented as polynomial and the polynomial. + */ + public operator fun C.times(other: P): P + // endregion + + // region Polynomial-constant relation + /** + * Returns sum of the constant represented as polynomial and the polynomial. + */ + public operator fun P.plus(other: C): P + /** + * Returns difference between the constant represented as polynomial and the polynomial. + */ + public operator fun P.minus(other: C): P + /** + * Returns product of the constant represented as polynomial and the polynomial. + */ + public operator fun P.times(other: C): P + // endregion + + // region Polynomial-polynomial relation + /** + * Returns the same polynomial. + */ + public operator fun P.unaryPlus(): P = this + /** + * Returns negation of the polynomial. + */ + public operator fun P.unaryMinus(): P + /** + * Returns sum of the polynomials. + */ + public operator fun P.plus(other: P): P + /** + * Returns difference of the polynomials. + */ + public operator fun P.minus(other: P): P + /** + * Returns product of the polynomials. + */ + public operator fun P.times(other: P): P + + /** + * Check if the instant is zero polynomial. + */ + public fun P.isZero(): Boolean = this == zeroPolynomial + /** + * Check if the instant is NOT zero polynomial. + */ + public fun P.isNotZero(): Boolean = this != zeroPolynomial + /** + * Check if the instant is unit polynomial. + */ + public fun P.isOne(): Boolean = this == onePolynomial + /** + * Check if the instant is NOT unit polynomial. + */ + public fun P.isNotOne(): Boolean = this != onePolynomial + /** + * Check if the instant is minus unit polynomial. + */ + public fun P.isMinusOne(): Boolean = this == -onePolynomial + /** + * Check if the instant is NOT minus unit polynomial. + */ + public fun P.isNotMinusOne(): Boolean = this != -onePolynomial + + /** + * Instance of zero polynomial (zero of the polynomial ring). + */ + public val zeroPolynomial: P + /** + * Instance of unit polynomial (unit of the polynomial ring). + */ + public val onePolynomial: P + + /** + * Checks equality of the polynomials. + */ + @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") + public fun P.equals(other: P): Boolean + // endregion + + // region Constant-rational relation + /** + * Returns sum of the constant represented as rational function and the rational function. + */ + public operator fun C.plus(other: R): R + /** + * Returns difference between the constant represented as polynomial and the rational function. + */ + public operator fun C.minus(other: R): R + /** + * Returns product of the constant represented as polynomial and the rational function. + */ + public operator fun C.times(other: R): R + // endregion + + // region Rational-constant relation + /** + * Returns sum of the constant represented as rational function and the rational function. + */ + public operator fun R.plus(other: C): R + /** + * Returns difference between the constant represented as rational function and the rational function. + */ + public operator fun R.minus(other: C): R + /** + * Returns product of the constant represented as rational function and the rational function. + */ + public operator fun R.times(other: C): R + // endregion + + // region Polynomial-rational relation + /** + * Returns sum of the polynomial represented as rational function and the rational function. + */ + public operator fun P.plus(other: R): R + /** + * Returns difference between the polynomial represented as polynomial and the rational function. + */ + public operator fun P.minus(other: R): R + /** + * Returns product of the polynomial represented as polynomial and the rational function. + */ + public operator fun P.times(other: R): R + // endregion + + // region Rational-polynomial relation + /** + * Returns sum of the polynomial represented as rational function and the rational function. + */ + public operator fun R.plus(other: P): R + /** + * Returns difference between the polynomial represented as rational function and the rational function. + */ + public operator fun R.minus(other: P): R + /** + * Returns product of the polynomial represented as rational function and the rational function. + */ + public operator fun R.times(other: P): R + // endregion + + // region Rational-rational relation + /** + * 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 + + /** + * Check if the instant is zero rational function. + */ + public fun R.isZero(): Boolean = this == zero + /** + * Check if the instant is NOT zero rational function. + */ + public fun R.isNotZero(): Boolean = this != zero + /** + * Check if the instant is unit rational function. + */ + public fun R.isOne(): Boolean = this == one + /** + * Check if the instant is NOT unit rational function. + */ + public fun R.isNotOne(): Boolean = this != one + /** + * Check if the instant is minus unit rational function. + */ + public fun R.isMinusOne(): Boolean = this == -one + /** + * Check if the instant is NOT minus unit rational function. + */ + public fun R.isNotMinusOne(): Boolean = this != -one + + /** + * 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 + + /** + * Checks equality of the rational functions. + */ + @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") + public fun R.equals(other: R): Boolean + // endregion + + // Not sure is it necessary... + // region Polynomial properties + /** + * 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 + + /** + * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. + */ + public fun P.isConstant(): Boolean = degree <= 0 + /** + * Checks if the instant is **not** constant polynomial (of degree no more than 0) over considered ring. + */ + public fun P.isNotConstant(): Boolean = !isConstant() + /** + * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. + */ + public fun P.isNonZeroConstant(): Boolean = degree == 0 + /** + * Checks if the instant is **not** constant non-zero polynomial (of degree no more than 0) over considered ring. + */ + public fun P.isNotNonZeroConstant(): Boolean = !isNonZeroConstant() + + public fun P.asConstantOrNull(): C? + + public fun P.asConstant(): C = asConstantOrNull() ?: error("Can not represent non-constant polynomial as a constant") + + // endregion + + // Not sure is it necessary... + // region Polynomial properties + /** + * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. + */ + public fun R.isConstant(): Boolean + /** + * Checks if the instant is **not** constant polynomial (of degree no more than 0) over considered ring. + */ + public fun R.isNotConstant(): Boolean = !isConstant() + /** + * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. + */ + public fun R.isNonZeroConstant(): Boolean + /** + * Checks if the instant is **not** constant non-zero polynomial (of degree no more than 0) over considered ring. + */ + public fun R.isNotNonZeroConstant(): Boolean = !isNonZeroConstant() + + public fun R.asConstantOrNull(): C? + + public fun R.asConstant(): C = asConstantOrNull() ?: error("Can not represent non-constant polynomial as a constant") + + // TODO: Перенести в реализацию +// fun R.substitute(argument: C): C +// fun R.substitute(argument: P): R +// fun R.substitute(argument: R): R +// +// fun R.asFunction(): (C) -> C = /*this::substitute*/ { this.substitute(it) } +// fun R.asFunctionOnConstants(): (C) -> C = /*this::substitute*/ { this.substitute(it) } +// fun P.asFunctionOnPolynomials(): (P) -> R = /*this::substitute*/ { this.substitute(it) } +// fun R.asFunctionOnRationalFunctions(): (R) -> R = /*this::substitute*/ { this.substitute(it) } +// +// operator fun R.invoke(argument: C): C = this.substitute(argument) +// operator fun R.invoke(argument: P): R = this.substitute(argument) +// operator fun R.invoke(argument: R): R = this.substitute(argument) + // endregion + + // region Legacy + override fun add(left: R, right: R): R = left + right + override fun multiply(left: R, right: R): R = left * right + // endregion +} \ No newline at end of file -- 2.34.1 From ffea8cc2234d869745fb0b99a8baedbf9cb51118 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sun, 13 Mar 2022 03:25:25 +0300 Subject: [PATCH 011/275] Regenerated READMEs --- README.md | 4 ++-- kmath-ast/README.md | 47 +++++++++++++++++++++++++++++--------- kmath-complex/README.md | 6 ++--- kmath-core/README.md | 6 ++--- kmath-ejml/README.md | 6 ++--- kmath-for-real/README.md | 6 ++--- kmath-functions/README.md | 6 ++--- kmath-jafama/README.md | 6 ++--- kmath-kotlingrad/README.md | 6 ++--- kmath-nd4j/README.md | 6 ++--- kmath-tensors/README.md | 6 ++--- 11 files changed, 65 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 99dd6d00f..76b8ce2f7 100644 --- a/README.md +++ b/README.md @@ -308,8 +308,8 @@ repositories { } dependencies { - api("space.kscience:kmath-core:0.3.0-dev-17") - // api("space.kscience:kmath-core-jvm:0.3.0-dev-17") for jvm-specific version + api("space.kscience:kmath-core:0.3.0-dev-19") + // api("space.kscience:kmath-core-jvm:0.3.0-dev-19") for jvm-specific version } ``` diff --git a/kmath-ast/README.md b/kmath-ast/README.md index bedf17486..9411befe3 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -10,7 +10,7 @@ Extensions to MST API: transformations, dynamic compilation and visualization. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-17`. +The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-19`. **Gradle:** ```gradle @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ast:0.3.0-dev-17' + implementation 'space.kscience:kmath-ast:0.3.0-dev-19' } ``` **Gradle Kotlin DSL:** @@ -31,7 +31,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ast:0.3.0-dev-17") + implementation("space.kscience:kmath-ast:0.3.0-dev-19") } ``` @@ -66,20 +66,19 @@ For example, the following code: ```kotlin import space.kscience.kmath.asm.compileToExpression -import space.kscience.kmath.complex.ComplexField +import space.kscience.kmath.operations.DoubleField -"x+2".parseMath().compileToExpression(ComplexField) +"x^3-x+3".parseMath().compileToExpression(DoubleField) ``` … leads to generation of bytecode, which can be decompiled to the following Java class: ```java -import java.util.Map; -import kotlin.jvm.functions.Function2; -import space.kscience.kmath.asm.internal.MapIntrinsics; -import space.kscience.kmath.complex.Complex; -import space.kscience.kmath.expressions.Expression; -import space.kscience.kmath.expressions.Symbol; +import java.util.*; +import kotlin.jvm.functions.*; +import space.kscience.kmath.asm.internal.*; +import space.kscience.kmath.complex.*; +import space.kscience.kmath.expressions.*; public final class CompiledExpression_45045_0 implements Expression { private final Object[] constants; @@ -91,6 +90,32 @@ public final class CompiledExpression_45045_0 implements Expression { } ``` +For `LongRing`, `IntRing`, and `DoubleField` specialization is supported for better performance: + +```java +import java.util.*; +import space.kscience.kmath.asm.internal.*; +import space.kscience.kmath.expressions.*; + +public final class CompiledExpression_-386104628_0 implements DoubleExpression { + private final SymbolIndexer indexer; + + public SymbolIndexer getIndexer() { + return this.indexer; + } + + public double invoke(double[] arguments) { + double var2 = arguments[0]; + return Math.pow(var2, 3.0D) - var2 + 3.0D; + } + + public final Double invoke(Map arguments) { + double var2 = ((Double)MapIntrinsics.getOrFail(arguments, "x")).doubleValue(); + return Math.pow(var2, 3.0D) - var2 + 3.0D; + } +} +``` + Setting JVM system property `space.kscience.kmath.ast.dump.generated.classes` to `1` makes the translator dump class files to program's working directory, so they can be reviewed manually. #### Limitations diff --git a/kmath-complex/README.md b/kmath-complex/README.md index 92f2435ba..cfaf43aa1 100644 --- a/kmath-complex/README.md +++ b/kmath-complex/README.md @@ -8,7 +8,7 @@ Complex and hypercomplex number systems in KMath. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-17`. +The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-19`. **Gradle:** ```gradle @@ -18,7 +18,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-complex:0.3.0-dev-17' + implementation 'space.kscience:kmath-complex:0.3.0-dev-19' } ``` **Gradle Kotlin DSL:** @@ -29,6 +29,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-complex:0.3.0-dev-17") + implementation("space.kscience:kmath-complex:0.3.0-dev-19") } ``` diff --git a/kmath-core/README.md b/kmath-core/README.md index e765ad50c..4e980baf5 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -15,7 +15,7 @@ performance calculations to code generation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-17`. +The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-19`. **Gradle:** ```gradle @@ -25,7 +25,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-core:0.3.0-dev-17' + implementation 'space.kscience:kmath-core:0.3.0-dev-19' } ``` **Gradle Kotlin DSL:** @@ -36,6 +36,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-core:0.3.0-dev-17") + implementation("space.kscience:kmath-core:0.3.0-dev-19") } ``` diff --git a/kmath-ejml/README.md b/kmath-ejml/README.md index fcd092bf1..24b36aa0d 100644 --- a/kmath-ejml/README.md +++ b/kmath-ejml/README.md @@ -9,7 +9,7 @@ EJML based linear algebra implementation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-17`. +The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-19`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ejml:0.3.0-dev-17' + implementation 'space.kscience:kmath-ejml:0.3.0-dev-19' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ejml:0.3.0-dev-17") + implementation("space.kscience:kmath-ejml:0.3.0-dev-19") } ``` diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md index 938327612..f6b02e6ad 100644 --- a/kmath-for-real/README.md +++ b/kmath-for-real/README.md @@ -9,7 +9,7 @@ Specialization of KMath APIs for Double numbers. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-17`. +The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-19`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-for-real:0.3.0-dev-17' + implementation 'space.kscience:kmath-for-real:0.3.0-dev-19' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-for-real:0.3.0-dev-17") + implementation("space.kscience:kmath-for-real:0.3.0-dev-19") } ``` diff --git a/kmath-functions/README.md b/kmath-functions/README.md index 3d4beee47..a7f4f9b6f 100644 --- a/kmath-functions/README.md +++ b/kmath-functions/README.md @@ -11,7 +11,7 @@ Functions and interpolations. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-17`. +The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-19`. **Gradle:** ```gradle @@ -21,7 +21,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-functions:0.3.0-dev-17' + implementation 'space.kscience:kmath-functions:0.3.0-dev-19' } ``` **Gradle Kotlin DSL:** @@ -32,6 +32,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-functions:0.3.0-dev-17") + implementation("space.kscience:kmath-functions:0.3.0-dev-19") } ``` diff --git a/kmath-jafama/README.md b/kmath-jafama/README.md index 760244751..3e0d9c418 100644 --- a/kmath-jafama/README.md +++ b/kmath-jafama/README.md @@ -7,7 +7,7 @@ Integration with [Jafama](https://github.com/jeffhain/jafama). ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-jafama:0.3.0-dev-17`. +The Maven coordinates of this project are `space.kscience:kmath-jafama:0.3.0-dev-19`. **Gradle:** ```gradle @@ -17,7 +17,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-jafama:0.3.0-dev-17' + implementation 'space.kscience:kmath-jafama:0.3.0-dev-19' } ``` **Gradle Kotlin DSL:** @@ -28,7 +28,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-jafama:0.3.0-dev-17") + implementation("space.kscience:kmath-jafama:0.3.0-dev-19") } ``` diff --git a/kmath-kotlingrad/README.md b/kmath-kotlingrad/README.md index 588ccb9b4..422ce4fb0 100644 --- a/kmath-kotlingrad/README.md +++ b/kmath-kotlingrad/README.md @@ -8,7 +8,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-kotlingrad:0.3.0-dev-17`. +The Maven coordinates of this project are `space.kscience:kmath-kotlingrad:0.3.0-dev-19`. **Gradle:** ```gradle @@ -18,7 +18,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-kotlingrad:0.3.0-dev-17' + implementation 'space.kscience:kmath-kotlingrad:0.3.0-dev-19' } ``` **Gradle Kotlin DSL:** @@ -29,6 +29,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-kotlingrad:0.3.0-dev-17") + implementation("space.kscience:kmath-kotlingrad:0.3.0-dev-19") } ``` diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index 7ca9cd4fd..23d529e72 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -9,7 +9,7 @@ ND4J based implementations of KMath abstractions. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-17`. +The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-19`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-nd4j:0.3.0-dev-17' + implementation 'space.kscience:kmath-nd4j:0.3.0-dev-19' } ``` **Gradle Kotlin DSL:** @@ -30,7 +30,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-nd4j:0.3.0-dev-17") + implementation("space.kscience:kmath-nd4j:0.3.0-dev-19") } ``` diff --git a/kmath-tensors/README.md b/kmath-tensors/README.md index 42ce91336..93f78e895 100644 --- a/kmath-tensors/README.md +++ b/kmath-tensors/README.md @@ -9,7 +9,7 @@ Common linear algebra operations on tensors. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.0-dev-17`. +The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.0-dev-19`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-tensors:0.3.0-dev-17' + implementation 'space.kscience:kmath-tensors:0.3.0-dev-19' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-tensors:0.3.0-dev-17") + implementation("space.kscience:kmath-tensors:0.3.0-dev-19") } ``` -- 2.34.1 From 843d63c76a46a55c683f4a8276663f5fecc6d6f5 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sun, 13 Mar 2022 03:27:00 +0300 Subject: [PATCH 012/275] Added support for all polynomials. But standard utilities still are not fully implemented. --- .../kmath/functions/AbstractPolynomial.kt | 47 +- .../functions/AbstractRationalFunction.kt | 2 - .../kmath/functions/LabeledPolynomial.kt | 927 ++++++++++++++++++ .../kmath/functions/NumberedPolynomial.kt | 689 +++++++++++++ .../kscience/kmath/functions/Polynomial.kt | 151 ++- .../kscience/kmath/functions/Variable.kt | 38 + .../kscience/kmath/functions/algebraicStub.kt | 51 + .../kmath/functions/labeledPolynomialUtil.kt | 490 +++++++++ .../kmath/functions/numberedPolynomialUtil.kt | 605 ++++++++++++ .../kmath/functions/polynomialUtil.kt | 6 +- 10 files changed, 2911 insertions(+), 95 deletions(-) create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Variable.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt index 237a72bcc..b7b7116f0 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt @@ -17,6 +17,9 @@ public interface AbstractPolynomial /** * 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 a coefficients in their terms. + * @param P the type of polynomials. */ @Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") public interface AbstractPolynomialSpace> : Ring

{ @@ -307,48 +310,4 @@ public interface AbstractPolynomialSpace> : Ring

override fun add(left: P, right: P): P = left + right override fun multiply(left: P, right: P): P = left * right // endregion - - public companion object { - // TODO: All of this should be moved to algebraic structures' place for utilities - // TODO: Move receiver to context receiver - /** - * Multiplication of element and integer. - * - * @receiver the multiplicand. - * @param other the multiplier. - * @return the difference. - */ - internal tailrec fun Group.optimizedMultiply(arg: C, other: Int): C = - when { - other == 0 -> zero - other == 1 -> arg - other == -1 -> -arg - other % 2 == 0 -> optimizedMultiply(arg + arg, other / 2) - other % 2 == 1 -> optimizedAddMultiplied(arg, arg + arg, other / 2) - other % 2 == -1 -> optimizedAddMultiplied(-arg, arg + arg, other / 2) - else -> error("Error in multiplication group instant by integer: got reminder by division by 2 different from 0, 1 and -1") - } - - // TODO: Move receiver to context receiver - /** - * Adds product of [arg] and [multiplier] to [base]. - * - * @receiver the algebra to provide multiplication. - * @param base the augend. - * @param arg the multiplicand. - * @param multiplier the multiplier. - * @return sum of the augend [base] and product of the multiplicand [arg] and the multiplier [multiplier]. - * @author Gleb Minaev - */ - internal tailrec fun Group.optimizedAddMultiplied(base: C, arg: C, multiplier: Int): C = - when { - multiplier == 0 -> base - multiplier == 1 -> base + arg - multiplier == -1 -> base - arg - multiplier % 2 == 0 -> optimizedAddMultiplied(base, arg + arg, multiplier / 2) - multiplier % 2 == 1 -> optimizedAddMultiplied(base + arg, arg + arg, multiplier / 2) - multiplier % 2 == -1 -> optimizedAddMultiplied(base + arg, arg + arg, multiplier / 2) - else -> error("Error in multiplication group instant by integer: got reminder by division by 2 different from 0, 1 and -1") - } - } } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt index 5cb570c9f..34050aa0f 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt @@ -5,8 +5,6 @@ package space.kscience.kmath.functions -import space.kscience.kmath.functions.AbstractPolynomialSpace.Companion.optimizedAddMultiplied -import space.kscience.kmath.functions.AbstractPolynomialSpace.Companion.optimizedMultiply import space.kscience.kmath.operations.* import kotlin.js.JsName import kotlin.jvm.JvmName diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt new file mode 100644 index 000000000..48f6f57fa --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -0,0 +1,927 @@ +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.* +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract +import kotlin.experimental.ExperimentalTypeInference +import kotlin.jvm.JvmName +import kotlin.math.max + + +/** + * Represents multivariate polynomials with labeled variables. + * + * @param C Ring in which the polynomial is considered. + */ +public class LabeledPolynomial +internal constructor( + /** + * Map that collects coefficients of the polynomial. Every non-zero monomial + * `a x_1^{d_1} ... x_n^{d_n}` is represented as pair "key-value" in the map, where value is coefficients `a` and + * key is map that associates variables in the monomial with multiplicity of them occurring in the monomial. + * For example polynomial + * ``` + * 5 a^2 c^3 - 6 b + 0 b c + * ``` + * has coefficients represented as + * ``` + * mapOf( + * mapOf( + * a to 2, + * c to 3 + * ) to 5, + * mapOf( + * b to 1 + * ) to (-6) + * ) + * ``` + * where `a`, `b` and `c` are corresponding [Variable] objects. + */ + public val coefficients: Map, C> +) : AbstractPolynomial { + override fun toString(): String = "LabeledPolynomial$coefficients" +} + +// region Internal utilities + +/** + * Represents internal [LabeledPolynomial] errors. + */ +internal class LabeledPolynomialError: Error { + constructor(): super() + constructor(message: String): super(message) + constructor(message: String?, cause: Throwable?): super(message, cause) + constructor(cause: Throwable?): super(cause) +} + +/** + * Throws an [LabeledPolynomialError] with the given [message]. + */ +internal fun labeledPolynomialError(message: Any): Nothing = throw LabeledPolynomialError(message.toString()) + +/** + * Returns the same degrees description of the monomial, but without zero degrees. + */ +internal fun Map.cleanUp() = filterValues { it > 0U } + +// endregion + +// region Constructors and converters + +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received +// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. +// * +// * @param pairs Collection of pairs that represent monomials. +// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. +// * +// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(A) +//internal fun > LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true): LabeledPolynomial { +// if (!toCheckInput) return LabeledPolynomial(coefs) +// +// // Map for cleaned coefficients. +// val fixedCoefs = mutableMapOf, C>() +// +// // Cleaning the degrees, summing monomials of the same degrees. +// for (entry in coefs) { +// val key = entry.key.cleanUp() +// val value = entry.value +// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value +// } +// +// // Removing zero monomials. +// return LabeledPolynomial( +// fixedCoefs +// .filter { it.value.isNotZero() } +// ) +//} +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received +// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. +// * +// * @param pairs Collection of pairs that represent monomials. +// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. +// * +// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(A) +//internal fun > LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean): LabeledPolynomial { +// if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) +// +// // Map for cleaned coefficients. +// val fixedCoefs = mutableMapOf, C>() +// +// // Cleaning the degrees, summing monomials of the same degrees. +// for (entry in pairs) { +// val key = entry.first.cleanUp() +// val value = entry.second +// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value +// } +// +// // Removing zero monomials. +// return LabeledPolynomial( +// fixedCoefs.filterValues { it.isNotZero() } +// ) +//} +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received +// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. +// * +// * @param pairs Collection of pairs that represents monomials. +// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. +// * +// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(A) +//internal fun > LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean): LabeledPolynomial { +// if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) +// +// // Map for cleaned coefficients. +// val fixedCoefs = mutableMapOf, C>() +// +// // Cleaning the degrees, summing monomials of the same degrees. +// for (entry in pairs) { +// val key = entry.first.cleanUp() +// val value = entry.second +// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value +// } +// +// // Removing zero monomials. +// return LabeledPolynomial( +// fixedCoefs.filterValues { it.isNotZero() } +// ) +//} +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received +// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. +// * +// * @param coefs Coefficients of the instants. +// * +// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(A) +//fun > LabeledPolynomial(coefs: Map, C>): LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received +// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. +// * +// * @param pairs Collection of pairs that represents monomials. +// * +// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(A) +//fun > LabeledPolynomial(pairs: Collection, C>>): LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received +// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. +// * +// * @param pairs Collection of pairs that represents monomials. +// * +// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(A) +//fun > LabeledPolynomial(vararg pairs: Pair, C>): LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received +// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. +// * +// * @param pairs Collection of pairs that represent monomials. +// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. +// * +// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(LabeledPolynomialSpace) +//internal fun > LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true): LabeledPolynomial { +// if (!toCheckInput) return LabeledPolynomial(coefs) +// +// // Map for cleaned coefficients. +// val fixedCoefs = mutableMapOf, C>() +// +// // Cleaning the degrees, summing monomials of the same degrees. +// for (entry in coefs) { +// val key = entry.key.cleanUp() +// val value = entry.value +// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value +// } +// +// // Removing zero monomials. +// return LabeledPolynomial( +// fixedCoefs +// .filter { it.value.isNotZero() } +// ) +//} +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received +// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. +// * +// * @param pairs Collection of pairs that represent monomials. +// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. +// * +// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(LabeledPolynomialSpace) +//internal fun > LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean): LabeledPolynomial { +// if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) +// +// // Map for cleaned coefficients. +// val fixedCoefs = mutableMapOf, C>() +// +// // Cleaning the degrees, summing monomials of the same degrees. +// for (entry in pairs) { +// val key = entry.first.cleanUp() +// val value = entry.second +// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value +// } +// +// // Removing zero monomials. +// return LabeledPolynomial( +// fixedCoefs.filterValues { it.isNotZero() } +// ) +//} +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received +// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. +// * +// * @param pairs Collection of pairs that represents monomials. +// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. +// * +// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(LabeledPolynomialSpace) +//internal fun > LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean): LabeledPolynomial { +// if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) +// +// // Map for cleaned coefficients. +// val fixedCoefs = mutableMapOf, C>() +// +// // Cleaning the degrees, summing monomials of the same degrees. +// for (entry in pairs) { +// val key = entry.first.cleanUp() +// val value = entry.second +// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value +// } +// +// // Removing zero monomials. +// return LabeledPolynomial( +// fixedCoefs.filterValues { it.isNotZero() } +// ) +//} +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received +// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. +// * +// * @param coefs Coefficients of the instants. +// * +// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(LabeledPolynomialSpace) +//fun > LabeledPolynomial(coefs: Map, C>): LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received +// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. +// * +// * @param pairs Collection of pairs that represents monomials. +// * +// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(LabeledPolynomialSpace) +//fun > LabeledPolynomial(pairs: Collection, C>>): LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received +// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. +// * +// * @param pairs Collection of pairs that represents monomials. +// * +// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(LabeledPolynomialSpace) +//fun > LabeledPolynomial(vararg pairs: Pair, C>): LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) +// +//fun C.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to this)) +// +//context(A) +//fun > Variable.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1U) to one)) +// +//context(LabeledPolynomialSpace) +//fun > Variable.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1U) to ring.one)) +// +//context(A) +//fun > Variable.asLabeledPolynomial(c: C) : LabeledPolynomial = +// if(c.isZero()) LabeledPolynomial(emptyMap()) +// else LabeledPolynomial(mapOf(mapOf(this to 1U) to c)) +// +//context(LabeledPolynomialSpace) +//fun > Variable.asLabeledPolynomial(c: C) : LabeledPolynomial = +// if(c.isZero()) zero +// else LabeledPolynomial(mapOf(mapOf(this to 1U) to c)) + +// endregion + +/** + * Space of polynomials. + * + * @param C the type of operated polynomials. + * @param A the intersection of [Ring] of [C] and [ScaleOperations] of [C]. + * @param ring the [A] instance. + */ +@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE", "INAPPLICABLE_JVM_NAME") +public class LabeledPolynomialSpace>( + public val ring: A, +) : AbstractPolynomialSpace> { + // region Constant-integer relation + @JvmName("constantIntPlus") + public override operator fun C.plus(other: Int): C = ring { optimizedAddMultiplied(this@plus, one, other) } + @JvmName("constantIntMinus") + public override operator fun C.minus(other: Int): C = ring { optimizedAddMultiplied(this@minus, one, -other) } + @JvmName("constantIntTimes") + public override operator fun C.times(other: Int): C = ring { optimizedMultiply(this@times, other) } + // endregion + + // region Integer-constant relation + @JvmName("intConstantPlus") + public override operator fun Int.plus(other: C): C = ring { optimizedAddMultiplied(other, one, this@plus) } + @JvmName("intConstantMinus") + public override operator fun Int.minus(other: C): C = ring { optimizedAddMultiplied(-other, one, this@minus) } + @JvmName("intConstantTimes") + public override operator fun Int.times(other: C): C = ring { optimizedMultiply(other, this@times) } + // endregion + + // region Variable-integer relation + public operator fun Variable.plus(other: Int): LabeledPolynomial = + if (other == 0) LabeledPolynomial(mapOf( + mapOf(this@plus to 1U) to ring.one, + )) + else LabeledPolynomial(mapOf( + mapOf(this@plus to 1U) to ring.one, + emptyMap() to ring.one * other, + )) + public operator fun Variable.minus(other: Int): LabeledPolynomial = + if (other == 0) LabeledPolynomial(mapOf( + mapOf(this@minus to 1U) to -ring.one, + )) + else LabeledPolynomial(mapOf( + mapOf(this@minus to 1U) to -ring.one, + emptyMap() to ring.one * other, + )) + public operator fun Variable.times(other: Int): LabeledPolynomial = + if (other == 0) zero + else LabeledPolynomial(mapOf( + mapOf(this to 1U) to ring.one * other, + )) + // endregion + + // region Integer-variable relation + public operator fun Int.plus(other: Variable): LabeledPolynomial = + if (this == 0) LabeledPolynomial(mapOf( + mapOf(other to 1U) to ring.one, + )) + else LabeledPolynomial(mapOf( + mapOf(other to 1U) to ring.one, + emptyMap() to ring.one * this@plus, + )) + public operator fun Int.minus(other: Variable): LabeledPolynomial = + if (this == 0) LabeledPolynomial(mapOf( + mapOf(other to 1U) to -ring.one, + )) + else LabeledPolynomial(mapOf( + mapOf(other to 1U) to -ring.one, + emptyMap() to ring.one * this@minus, + )) + public operator fun Int.times(other: Variable): LabeledPolynomial = + if (this == 0) zero + else LabeledPolynomial(mapOf( + mapOf(other to 1U) to ring.one * this@times, + )) + // endregion + + // region Polynomial-integer relation + public override operator fun LabeledPolynomial.plus(other: Int): LabeledPolynomial = + if (other == 0) this + else + LabeledPolynomial( + coefficients + .toMutableMap() + .apply { + val degs = emptyMap() + + val result = getOrElse(degs) { ring.zero } + other + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + public override operator fun LabeledPolynomial.minus(other: Int): LabeledPolynomial = + if (other == 0) this + else + LabeledPolynomial( + coefficients + .toMutableMap() + .apply { + val degs = emptyMap() + + val result = getOrElse(degs) { ring.zero } - other + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + public override operator fun LabeledPolynomial.times(other: Int): LabeledPolynomial = + if (other == 0) zero + else LabeledPolynomial( + coefficients + .applyAndRemoveZeros { + mapValues { (_, c) -> c * other } + } + ) + // endregion + + // region Integer-polynomial relation + public override operator fun Int.plus(other: LabeledPolynomial): LabeledPolynomial = + if (this == 0) other + else + LabeledPolynomial( + other.coefficients + .toMutableMap() + .apply { + val degs = emptyMap() + + val result = this@plus + getOrElse(degs) { ring.zero } + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + public override operator fun Int.minus(other: LabeledPolynomial): LabeledPolynomial = + if (this == 0) other + else + LabeledPolynomial( + other.coefficients + .toMutableMap() + .apply { + val degs = emptyMap() + + val result = this@minus - getOrElse(degs) { ring.zero } + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + public override operator fun Int.times(other: LabeledPolynomial): LabeledPolynomial = + if (this == 0) zero + else LabeledPolynomial( + other.coefficients + .applyAndRemoveZeros { + mapValues { (_, c) -> this@times * c } + } + ) + // endregion + + // region Constant-constant relation + @JvmName("constantUnaryMinus") + override operator fun C.unaryMinus(): C = ring { -this@unaryMinus } + @JvmName("constantPlus") + override operator fun C.plus(other: C): C = ring { this@plus + other } + @JvmName("constantMinus") + override operator fun C.minus(other: C): C = ring { this@minus - other } + @JvmName("constantTimes") + override operator fun C.times(other: C): C = ring { this@times * other } + @JvmName("constantIsZero") + public override fun C.isZero(): Boolean = ring { this == zero } + @JvmName("constantIsNotZero") + public override fun C.isNotZero(): Boolean = ring { this != zero } + @JvmName("constantIsOne") + public override fun C.isOne(): Boolean = ring { this == one } + @JvmName("constantIsNotOne") + public override fun C.isNotOne(): Boolean = ring { this != one } + @JvmName("constantIsMinusOne") + public override fun C.isMinusOne(): Boolean = ring { this == -one } + @JvmName("constantIsNotMinusOne") + public override fun C.isNotMinusOne(): Boolean = ring { this != -one } + // endregion + + // region Constant-variable relation + public operator fun C.plus(other: Variable): LabeledPolynomial = + if (isZero()) LabeledPolynomial(mapOf( + mapOf(other to 1U) to ring.one, + )) + else LabeledPolynomial(mapOf( + mapOf(other to 1U) to ring.one, + emptyMap() to this@plus, + )) + public operator fun C.minus(other: Variable): LabeledPolynomial = + if (isZero()) LabeledPolynomial(mapOf( + mapOf(other to 1U) to -ring.one, + )) + else LabeledPolynomial(mapOf( + mapOf(other to 1U) to -ring.one, + emptyMap() to this@minus, + )) + public operator fun C.times(other: Variable): LabeledPolynomial = + if (isZero()) zero + else LabeledPolynomial(mapOf( + mapOf(other to 1U) to this@times, + )) + // endregion + + // region Variable-constant relation + public operator fun Variable.plus(other: C): LabeledPolynomial = + if (other.isZero()) LabeledPolynomial(mapOf( + mapOf(this@plus to 1U) to ring.one, + )) + else LabeledPolynomial(mapOf( + mapOf(this@plus to 1U) to ring.one, + emptyMap() to other, + )) + public operator fun Variable.minus(other: C): LabeledPolynomial = + if (other.isZero()) LabeledPolynomial(mapOf( + mapOf(this@minus to 1U) to -ring.one, + )) + else LabeledPolynomial(mapOf( + mapOf(this@minus to 1U) to -ring.one, + emptyMap() to other, + )) + public operator fun Variable.times(other: C): LabeledPolynomial = + if (other.isZero()) zero + else LabeledPolynomial(mapOf( + mapOf(this@times to 1U) to other, + )) + // endregion + + // region Constant-polynomial relation + override operator fun C.plus(other: LabeledPolynomial): LabeledPolynomial = + if (this.isZero()) other + else with(other.coefficients) { + if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@plus)) + else LabeledPolynomial( + toMutableMap() + .apply { + val degs = emptyMap() + + val result = this@plus + getOrElse(degs) { ring.zero } + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + } + override operator fun C.minus(other: LabeledPolynomial): LabeledPolynomial = + if (this.isZero()) other + else with(other.coefficients) { + if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@minus)) + else LabeledPolynomial( + toMutableMap() + .apply { + forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } + + val degs = emptyMap() + + val result = this@minus - getOrElse(degs) { ring.zero } + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + } + override operator fun C.times(other: LabeledPolynomial): LabeledPolynomial = + if (this.isZero()) zero + else LabeledPolynomial( + other.coefficients + .applyAndRemoveZeros { + mapValues { (_, c) -> this@times * c } + } + ) + // endregion + + // region Polynomial-constant relation + /** + * Returns sum of the polynomials. [other] is interpreted as [UnivariatePolynomial]. + */ + override operator fun LabeledPolynomial.plus(other: C): LabeledPolynomial = + if (other.isZero()) this + else with(coefficients) { + if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to other)) + else LabeledPolynomial( + toMutableMap() + .apply { + val degs = emptyMap() + + val result = getOrElse(degs) { ring.zero } + other + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + } + /** + * Returns difference of the polynomials. [other] is interpreted as [UnivariatePolynomial]. + */ + override operator fun LabeledPolynomial.minus(other: C): LabeledPolynomial = + if (other.isZero()) this + else with(coefficients) { + if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to other)) + else LabeledPolynomial( + toMutableMap() + .apply { + forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } + + val degs = emptyMap() + + val result = getOrElse(degs) { ring.zero } - other + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + } + /** + * Returns product of the polynomials. [other] is interpreted as [UnivariatePolynomial]. + */ + override operator fun LabeledPolynomial.times(other: C): LabeledPolynomial = + if (other.isZero()) zero + else LabeledPolynomial( + coefficients + .applyAndRemoveZeros { + mapValues { (_, c) -> c * other } + } + ) + // endregion + + // region Variable-variable relation + public operator fun Variable.plus(other: Variable): LabeledPolynomial = + if (this == other) LabeledPolynomial(mapOf( + mapOf(this to 1U) to ring.one * 2 + )) + else LabeledPolynomial(mapOf( + mapOf(this to 1U) to ring.one, + mapOf(other to 1U) to ring.one, + )) + public operator fun Variable.minus(other: Variable): LabeledPolynomial = + if (this == other) zero + else LabeledPolynomial(mapOf( + mapOf(this to 1U) to ring.one, + mapOf(other to 1U) to -ring.one, + )) + public operator fun Variable.times(other: Variable): LabeledPolynomial = + if (this == other) LabeledPolynomial(mapOf( + mapOf(this to 2U) to ring.one + )) + else LabeledPolynomial(mapOf( + mapOf(this to 1U, other to 1U) to ring.one, + )) + // endregion + + // region Variable-polynomial relation + public operator fun Variable.plus(other: LabeledPolynomial): LabeledPolynomial = + with(other.coefficients) { + if (isEmpty()) LabeledPolynomial(mapOf(mapOf(this@plus to 1u) to ring.one)) + else LabeledPolynomial( + toMutableMap() + .apply { + val degs = mapOf(this@plus to 1U) + + val result = ring.one + getOrElse(degs) { ring.zero } + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + } + public operator fun Variable.minus(other: LabeledPolynomial): LabeledPolynomial = + with(other.coefficients) { + if (isEmpty()) LabeledPolynomial(mapOf(mapOf(this@minus to 1u) to ring.one)) + else LabeledPolynomial( + toMutableMap() + .apply { + forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } + + val degs = mapOf(this@minus to 1U) + + val result = ring.one - getOrElse(degs) { ring.zero } + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + } + public operator fun Variable.times(other: LabeledPolynomial): LabeledPolynomial = + LabeledPolynomial( + other.coefficients + .mapKeys { (degs, _) -> degs.toMutableMap().also{ it[this] = if (this in it) it[this]!! + 1U else 1U } } + ) + // endregion + + // region Polynomial-variable relation + public operator fun LabeledPolynomial.plus(other: Variable): LabeledPolynomial = + with(coefficients) { + if (isEmpty()) LabeledPolynomial(mapOf(mapOf(other to 1u) to ring.one)) + else LabeledPolynomial( + toMutableMap() + .apply { + val degs = mapOf(other to 1U) + + val result = ring.one + getOrElse(degs) { ring.zero } + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + } + public operator fun LabeledPolynomial.minus(other: Variable): LabeledPolynomial = + with(coefficients) { + if (isEmpty()) LabeledPolynomial(mapOf(mapOf(other to 1u) to ring.one)) + else LabeledPolynomial( + toMutableMap() + .apply { + val degs = mapOf(other to 1U) + + val result = ring.one - getOrElse(degs) { ring.zero } + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + } + public operator fun LabeledPolynomial.times(other: Variable): LabeledPolynomial = + LabeledPolynomial( + coefficients + .mapKeys { (degs, _) -> degs.toMutableMap().also{ it[other] = if (other in it) it[other]!! + 1U else 1U } } + ) + // endregion + + // region Polynomial-polynomial relation + /** + * Returns negation of the polynomial. + */ + override fun LabeledPolynomial.unaryMinus(): LabeledPolynomial = + LabeledPolynomial( + coefficients.mapValues { -it.value } + ) + /** + * Returns sum of the polynomials. + */ + override operator fun LabeledPolynomial.plus(other: LabeledPolynomial): LabeledPolynomial = + LabeledPolynomial( + coefficients + .applyAndRemoveZeros { + other.coefficients + .mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value } + } + ) + /** + * Returns difference of the polynomials. + */ + override operator fun LabeledPolynomial.minus(other: LabeledPolynomial): LabeledPolynomial = + LabeledPolynomial( + coefficients + .applyAndRemoveZeros { + other.coefficients + .mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value } + } + ) + /** + * Returns product of the polynomials. + */ + override operator fun LabeledPolynomial.times(other: LabeledPolynomial): LabeledPolynomial = + when { + isZero() -> zero + other.isZero() -> zero + else -> LabeledPolynomial( + buildCoefficients { + for ((degs1, c1) in coefficients) for ((degs2, c2) in other.coefficients) { + val degs = degs1.toMutableMap() + degs2.mapValuesTo(degs) { (variable, deg) -> degs.getOrElse(variable) { 0u } + deg } + val c = c1 * c2 + this[degs] = if (degs in this) this[degs]!! + c else c + } + } + ) + } + + override val zero: LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to ring.zero)) + override val one: LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to ring.one)) + + // TODO: Docs + @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") + override fun LabeledPolynomial.equals(other: LabeledPolynomial): Boolean = + when { + this === other -> true + else -> coefficients.size == other.coefficients.size && + coefficients.all { (key, value) -> with(other.coefficients) { key in this && this[key] == value } } + } + // endregion + + // Not sure is it necessary... + // region Polynomial properties + /** + * 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, c) -> if (c.isZero()) -1 else 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 val LabeledPolynomial.degrees: Map + get() = + buildMap { + coefficients.entries.forEach { (degs, c) -> + if (c.isNotZero()) degs.mapValuesTo(this) { (variable, deg) -> + max(getOrElse(variable) { 0u }, deg) + } + } + } + /** + * Set of all variables that appear in the polynomial in positive exponents. + */ + public val LabeledPolynomial.variables: Set + get() = + buildSet { + coefficients.entries.forEach { (degs, c) -> if (c.isNotZero()) addAll(degs.keys) } + } + /** + * Count of all variables that appear in the polynomial in positive exponents. + */ + public val LabeledPolynomial.countOfVariables: Int get() = variables.size + + /** + * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. + */ + override fun LabeledPolynomial.isConstant(): Boolean = + coefficients.all { (degs, c) -> degs.isEmpty() || c.isZero() } + /** + * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. + */ + override fun LabeledPolynomial.isNonZeroConstant(): Boolean = + with(coefficients) { + var foundAbsoluteTermAndItIsNotZero = false + for ((degs, c) in this) { + if (degs.isNotEmpty()) if (c.isNotZero()) return@with false + else { + if (c.isZero()) return@with false + else foundAbsoluteTermAndItIsNotZero = true + } + } + foundAbsoluteTermAndItIsNotZero + } + + override fun LabeledPolynomial.asConstantOrNull(): C? = + with(coefficients) { + if(isConstant()) getOrElse(emptyMap()) { ring.zero } + else null + } + +// @Suppress("NOTHING_TO_INLINE") +// public inline fun LabeledPolynomial.substitute(argument: Map): LabeledPolynomial = this.substitute(ring, argument) +// @Suppress("NOTHING_TO_INLINE") +// @JvmName("substitutePolynomial") +// public inline fun LabeledPolynomial.substitute(argument: Map>): LabeledPolynomial = this.substitute(ring, argument) +// +// @Suppress("NOTHING_TO_INLINE") +// public inline fun LabeledPolynomial.asFunction(): (Map) -> LabeledPolynomial = { this.substitute(ring, it) } +// @Suppress("NOTHING_TO_INLINE") +// public inline fun LabeledPolynomial.asFunctionOnConstants(): (Map) -> LabeledPolynomial = { this.substitute(ring, it) } +// @Suppress("NOTHING_TO_INLINE") +// public inline fun LabeledPolynomial.asFunctionOnPolynomials(): (Map>) -> LabeledPolynomial = { this.substitute(ring, it) } +// +// @Suppress("NOTHING_TO_INLINE") +// public inline operator fun LabeledPolynomial.invoke(argument: Map): LabeledPolynomial = this.substitute(ring, argument) +// @Suppress("NOTHING_TO_INLINE") +// @JvmName("invokePolynomial") +// public inline operator fun LabeledPolynomial.invoke(argument: Map>): LabeledPolynomial = this.substitute(ring, argument) + // endregion + + // region Legacy + @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") + override inline fun add(left: LabeledPolynomial, right: LabeledPolynomial): LabeledPolynomial = left + right + @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") + override inline fun multiply(left: LabeledPolynomial, right: LabeledPolynomial): LabeledPolynomial = left * right + // endregion + + // region Utilities + // TODO: Move to region internal utilities with context receiver + internal fun MutableMap, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : MutableMap, C> { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + block() + for ((degs, c) in this) if (c.isZero()) this.remove(degs) + return this + } + internal fun Map, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : Map, C> = + toMutableMap().applyAndRemoveZeros(block) + @OptIn(ExperimentalTypeInference::class) + internal fun buildCoefficients(@BuilderInference builderAction: MutableMap, C>.() -> Unit): Map, C> { + contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } + return buildMap { + builderAction() + for ((degs, c) in this) if (c.isZero()) this.remove(degs) + } + } + // endregion +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt new file mode 100644 index 000000000..f1ad9a74f --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -0,0 +1,689 @@ +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.* +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract +import kotlin.experimental.ExperimentalTypeInference +import kotlin.jvm.JvmName +import kotlin.math.max + + +/** + * Polynomial model without fixation on specific context they are applied to. + * + * @param C the type of constants. + */ +public class NumberedPolynomial +internal constructor( + /** + * Map that collects coefficients of the polynomial. Every monomial `a x_1^{d_1} ... x_n^{d_n}` is represented as + * pair "key-value" in the map, where value is coefficients `a` and + * key is list that associates index of every variable in the monomial with multiplicity of the variable occurring + * in the monomial. For example coefficients of polynomial `5 x_1^2 x_3^3 - 6 x_2` can be represented as + * ``` + * mapOf( + * listOf(2, 0, 3) to 5, + * listOf(0, 1) to (-6), + * ) + * ``` + * and also as + * ``` + * mapOf( + * listOf(2, 0, 3) to 5, + * listOf(0, 1) to (-6), + * listOf(0, 1, 1) to 0, + * ) + * ``` + * It is recommended not to put zero monomials into the map, but is not prohibited. Lists of degrees always do not + * contain any zeros on end, but can contain zeros on start or anywhere in middle. + */ + public val coefficients: Map, C> +) : AbstractPolynomial { + override fun toString(): String = "NumberedPolynomial$coefficients" +} + +// region Internal utilities + +/** + * Represents internal [Polynomial] errors. + */ +internal class NumberedPolynomialError : Error { + constructor(): super() + constructor(message: String): super(message) + constructor(message: String?, cause: Throwable?): super(message, cause) + constructor(cause: Throwable?): super(cause) +} + +/** + * Throws an [PolynomialError] with the given [message]. + */ +internal fun numberedPolynomialError(message: Any): Nothing = throw PolynomialError(message.toString()) + +/** + * 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) + +// endregion + +// region Constructors and converters +// Waiting for context receivers :( TODO: Replace with context receivers when they will be available + +//context(A) +//@Suppress("FunctionName") +//internal fun > NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean): NumberedPolynomial { +// if (!toCheckInput) return NumberedPolynomial(coefs) +// +// val fixedCoefs = mutableMapOf, C>() +// +// for (entry in coefs) { +// val key = entry.key.cleanUp() +// val value = entry.value +// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value +// } +// +// return NumberedPolynomial( +// fixedCoefs +// .filter { it.value.isNotZero() } +// ) +//} +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received +// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. +// * +// * @param pairs Collection of pairs that represent monomials. +// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. +// * +// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(A) +//@Suppress("FunctionName") +//internal fun > NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean): NumberedPolynomial { +// if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) +// +// val fixedCoefs = mutableMapOf, C>() +// +// for (entry in pairs) { +// val key = entry.first.cleanUp() +// val value = entry.second +// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value +// } +// +// return NumberedPolynomial( +// fixedCoefs +// .filter { it.value.isNotZero() } +// ) +//} +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received +// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. +// * +// * @param pairs Collection of pairs that represent monomials. +// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. +// * +// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(A) +//@Suppress("FunctionName") +//internal fun > NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean): NumberedPolynomial = +// NumberedPolynomial(pairs.toMap(), toCheckInput) +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received +// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. +// * +// * @param coefs Coefficients of the instants. +// * +// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(A) +//public fun > NumberedPolynomial(coefs: Map, C>) = NumberedPolynomial(coefs, toCheckInput = true) +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received +// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. +// * +// * @param pairs Collection of pairs that represent monomials. +// * +// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(A) +//public fun > NumberedPolynomial(pairs: Collection, C>>) = NumberedPolynomial(pairs, toCheckInput = true) +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received +// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. +// * +// * @param pairs Collection of pairs that represent monomials. +// * +// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(A) +//public fun > NumberedPolynomial(vararg pairs: Pair, C>) = NumberedPolynomial(*pairs, toCheckInput = true) +// +//context(NumberedPolynomialSpace) +//@Suppress("FunctionName") +//internal fun > NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean): NumberedPolynomial { +// if (!toCheckInput) return NumberedPolynomial(coefs) +// +// val fixedCoefs = mutableMapOf, C>() +// +// for (entry in coefs) { +// val key = entry.key.cleanUp() +// val value = entry.value +// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value +// } +// +// return NumberedPolynomial( +// fixedCoefs +// .filter { it.value.isNotZero() } +// ) +//} +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received +// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. +// * +// * @param pairs Collection of pairs that represent monomials. +// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. +// * +// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(NumberedPolynomialSpace) +//@Suppress("FunctionName") +//internal fun > NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean): NumberedPolynomial { +// if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) +// +// val fixedCoefs = mutableMapOf, C>() +// +// for (entry in pairs) { +// val key = entry.first.cleanUp() +// val value = entry.second +// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value +// } +// +// return NumberedPolynomial( +// fixedCoefs +// .filter { it.value.isNotZero() } +// ) +//} +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received +// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. +// * +// * @param pairs Collection of pairs that represent monomials. +// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. +// * +// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(NumberedPolynomialSpace) +//@Suppress("FunctionName") +//internal fun > NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean): NumberedPolynomial = +// NumberedPolynomial(pairs.toList(), toCheckInput) +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received +// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. +// * +// * @param coefs Coefficients of the instants. +// * +// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(NumberedPolynomialSpace) +//public fun > NumberedPolynomial(coefs: Map, C>) = NumberedPolynomial(coefs, toCheckInput = true) +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received +// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. +// * +// * @param pairs Collection of pairs that represent monomials. +// * +// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(NumberedPolynomialSpace) +//public fun > NumberedPolynomial(pairs: Collection, C>>) = NumberedPolynomial(pairs, toCheckInput = true) +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received +// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. +// * +// * @param pairs Collection of pairs that represent monomials. +// * +// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(NumberedPolynomialSpace) +//public fun > NumberedPolynomial(vararg pairs: Pair, C>) = NumberedPolynomial(*pairs, toCheckInput = true) + +public fun > C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(emptyList() to this)) + +// endregion + +/** + * Space of polynomials. + * + * @param C the type of operated polynomials. + * @param A the intersection of [Ring] of [C] and [ScaleOperations] of [C]. + * @param ring the [A] instance. + */ +@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE", "INAPPLICABLE_JVM_NAME") +public class NumberedPolynomialSpace>( + public val ring: A, +) : AbstractPolynomialSpace> { + // region Constant-integer relation + @JvmName("constantIntPlus") + public override operator fun C.plus(other: Int): C = ring { optimizedAddMultiplied(this@plus, one, other) } + @JvmName("constantIntMinus") + public override operator fun C.minus(other: Int): C = ring { optimizedAddMultiplied(this@minus, one, -other) } + @JvmName("constantIntTimes") + public override operator fun C.times(other: Int): C = ring { optimizedMultiply(this@times, other) } + // endregion + + // region Integer-constant relation + @JvmName("intConstantPlus") + public override operator fun Int.plus(other: C): C = ring { optimizedAddMultiplied(other, one, this@plus) } + @JvmName("intConstantMinus") + public override operator fun Int.minus(other: C): C = ring { optimizedAddMultiplied(-other, one, this@minus) } + @JvmName("intConstantTimes") + public override operator fun Int.times(other: C): C = ring { optimizedMultiply(other, this@times) } + // endregion + + // region Polynomial-integer relation + public override operator fun NumberedPolynomial.plus(other: Int): NumberedPolynomial = + if (other == 0) this + else + NumberedPolynomial( + coefficients + .toMutableMap() + .apply { + val degs = emptyList() + + val result = getOrElse(degs) { ring.zero } + other + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + public override operator fun NumberedPolynomial.minus(other: Int): NumberedPolynomial = + if (other == 0) this + else + NumberedPolynomial( + coefficients + .toMutableMap() + .apply { + val degs = emptyList() + + val result = getOrElse(degs) { ring.zero } - other + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + public override operator fun NumberedPolynomial.times(other: Int): NumberedPolynomial = + if (other == 0) zero + else NumberedPolynomial( + coefficients + .applyAndRemoveZeros { + mapValues { (_, c) -> c * other } + } + ) + // endregion + + // region Integer-polynomial relation + public override operator fun Int.plus(other: NumberedPolynomial): NumberedPolynomial = + if (this == 0) other + else + NumberedPolynomial( + other.coefficients + .toMutableMap() + .apply { + val degs = emptyList() + + val result = this@plus + getOrElse(degs) { ring.zero } + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + public override operator fun Int.minus(other: NumberedPolynomial): NumberedPolynomial = + if (this == 0) other + else + NumberedPolynomial( + other.coefficients + .toMutableMap() + .apply { + val degs = emptyList() + + val result = this@minus - getOrElse(degs) { ring.zero } + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + public override operator fun Int.times(other: NumberedPolynomial): NumberedPolynomial = + if (this == 0) zero + else NumberedPolynomial( + other.coefficients + .applyAndRemoveZeros { + mapValues { (_, c) -> this@times * c } + } + ) + // endregion + + // region Constant-constant relation + @JvmName("constantUnaryMinus") + override operator fun C.unaryMinus(): C = ring { -this@unaryMinus } + @JvmName("constantPlus") + override operator fun C.plus(other: C): C = ring { this@plus + other } + @JvmName("constantMinus") + override operator fun C.minus(other: C): C = ring { this@minus - other } + @JvmName("constantTimes") + override operator fun C.times(other: C): C = ring { this@times * other } + @JvmName("constantIsZero") + public override fun C.isZero(): Boolean = ring { this == zero } + @JvmName("constantIsNotZero") + public override fun C.isNotZero(): Boolean = ring { this != zero } + @JvmName("constantIsOne") + public override fun C.isOne(): Boolean = ring { this == one } + @JvmName("constantIsNotOne") + public override fun C.isNotOne(): Boolean = ring { this != one } + @JvmName("constantIsMinusOne") + public override fun C.isMinusOne(): Boolean = ring { this == -one } + @JvmName("constantIsNotMinusOne") + public override fun C.isNotMinusOne(): Boolean = ring { this != -one } + // endregion + + // region Constant-polynomial relation + override operator fun C.plus(other: NumberedPolynomial): NumberedPolynomial = + if (this.isZero()) other + else with(other.coefficients) { + if (isEmpty()) NumberedPolynomial(mapOf(emptyList() to this@plus)) + else NumberedPolynomial( + toMutableMap() + .apply { + val degs = emptyList() + + val result = this@plus + getOrElse(degs) { ring.zero } + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + } + override operator fun C.minus(other: NumberedPolynomial): NumberedPolynomial = + if (this.isZero()) -other + else with(other.coefficients) { + if (isEmpty()) NumberedPolynomial(mapOf(listOf() to this@minus)) + else NumberedPolynomial( + toMutableMap() + .apply { + forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } + + val degs = emptyList() + + val result = this@minus - getOrElse(degs) { ring.zero } + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + } + override operator fun C.times(other: NumberedPolynomial): NumberedPolynomial = + if (this.isZero()) zero + else NumberedPolynomial( + other.coefficients + .applyAndRemoveZeros { + mapValues { (_, c) -> this@times * c } + } + ) + // endregion + + // region Polynomial-constant relation + /** + * Returns sum of the polynomials. [other] is interpreted as [NumberedPolynomial]. + */ + override operator fun NumberedPolynomial.plus(other: C): NumberedPolynomial = + if (other.isZero()) this + else with(coefficients) { + if (isEmpty()) NumberedPolynomial(mapOf(listOf() to other)) + else NumberedPolynomial( + toMutableMap() + .apply { + val degs = emptyList() + + val result = getOrElse(degs) { ring.zero } + other + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + } + /** + * Returns difference of the polynomials. [other] is interpreted as [NumberedPolynomial]. + */ + override operator fun NumberedPolynomial.minus(other: C): NumberedPolynomial = + if (other.isZero()) this + else with(coefficients) { + if (isEmpty()) NumberedPolynomial(mapOf(listOf() to other)) + else NumberedPolynomial( + toMutableMap() + .apply { + val degs = emptyList() + + val result = getOrElse(degs) { ring.zero } - other + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + } + /** + * Returns product of the polynomials. [other] is interpreted as [NumberedPolynomial]. + */ + override operator fun NumberedPolynomial.times(other: C): NumberedPolynomial = + if (other.isZero()) zero + else NumberedPolynomial( + coefficients + .applyAndRemoveZeros { + mapValues { (_, c) -> c * other } + } + ) + // endregion + + // region Polynomial-polynomial relation + /** + * Returns negation of the polynomial. + */ + override fun NumberedPolynomial.unaryMinus(): NumberedPolynomial = + NumberedPolynomial( + coefficients.mapValues { -it.value } + ) + /** + * Returns sum of the polynomials. + */ + override operator fun NumberedPolynomial.plus(other: NumberedPolynomial): NumberedPolynomial = + NumberedPolynomial( + coefficients + .applyAndRemoveZeros { + other.coefficients + .mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value } + } + ) + /** + * Returns difference of the polynomials. + */ + override operator fun NumberedPolynomial.minus(other: NumberedPolynomial): NumberedPolynomial = + NumberedPolynomial( + coefficients + .applyAndRemoveZeros { + other.coefficients + .mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value } + } + ) + /** + * Returns product of the polynomials. + */ + override operator fun NumberedPolynomial.times(other: NumberedPolynomial): NumberedPolynomial = + when { + isZero() -> zero + other.isZero() -> zero + else -> + NumberedPolynomial( + buildCoefficients { + 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 + this[degs] = if (degs in this) this[degs]!! + c else c + } + } + ) + } + + public override fun NumberedPolynomial.isZero(): Boolean = coefficients.values.all { it.isZero() } + public override fun NumberedPolynomial.isNotZero(): Boolean = coefficients.values.any { it.isNotZero() } + public override fun NumberedPolynomial.isOne(): Boolean = + with(coefficients) { + var foundAbsoluteTermAndItIsOne = false + for ((degs, c) in this) { + if (degs.isNotEmpty()) if (c.isNotZero()) return@with false + else { + if (c.isNotOne()) return@with false + else foundAbsoluteTermAndItIsOne = true + } + } + foundAbsoluteTermAndItIsOne + } + public override fun NumberedPolynomial.isNotOne(): Boolean = !isOne() + public override fun NumberedPolynomial.isMinusOne(): Boolean = + with(coefficients) { + var foundAbsoluteTermAndItIsMinusOne = false + for ((degs, c) in this) { + if (degs.isNotEmpty()) if (c.isNotZero()) return@with false + else { + if (c.isNotMinusOne()) return@with false + else foundAbsoluteTermAndItIsMinusOne = true + } + } + foundAbsoluteTermAndItIsMinusOne + } + public override fun NumberedPolynomial.isNotMinusOne(): Boolean = !isMinusOne() + + override val zero: NumberedPolynomial = NumberedPolynomial(emptyMap()) + override val one: NumberedPolynomial = + NumberedPolynomial( + mapOf( + listOf() to ring.one // 1 * x_1^0 * x_2^0 * ... + ) + ) + + // TODO: Docs + @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") + override fun NumberedPolynomial.equals(other: NumberedPolynomial): Boolean = + when { + this === other -> true + else -> coefficients.size == other.coefficients.size && + coefficients.all { (key, value) -> with(other.coefficients) { key in this && this[key] == value } } + } + // endregion + + // Not sure is it necessary... + // region Polynomial properties + /** + * Count of all variables that appear in the polynomial in positive exponents. + */ + public val NumberedPolynomial.countOfVariables: Int + get() = coefficients.entries.maxOfOrNull { (degs, c) -> if (c.isZero()) 0 else degs.size } ?: 0 + /** + * 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.entries.maxOfOrNull { (degs, c) -> if (c.isZero()) -1 else 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 size of the list is [countOfVariables]. + */ + public val NumberedPolynomial.degrees: List + get() = + buildList(countOfVariables) { + repeat(countOfVariables) { add(0U) } + coefficients.entries.forEach { (degs, c) -> + if (c.isNotZero()) degs.forEachIndexed { index, deg -> + this[index] = max(this[index], deg) + } + } + } + + /** + * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. + */ + override fun NumberedPolynomial.isConstant(): Boolean = + coefficients.all { (degs, c) -> degs.isEmpty() || c.isZero() } + /** + * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. + */ + override fun NumberedPolynomial.isNonZeroConstant(): Boolean = + with(coefficients) { + var foundAbsoluteTermAndItIsNotZero = false + for ((degs, c) in this) { + if (degs.isNotEmpty()) if (c.isNotZero()) return@with false + else { + if (c.isZero()) return@with false + else foundAbsoluteTermAndItIsNotZero = true + } + } + foundAbsoluteTermAndItIsNotZero + } + + override fun NumberedPolynomial.asConstantOrNull(): C? = + with(coefficients) { + if(isConstant()) getOrElse(emptyList()) { ring.zero } + else null + } + + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedPolynomial.substitute(argument: Map): NumberedPolynomial = this.substitute(ring, argument) + @Suppress("NOTHING_TO_INLINE") + @JvmName("substitutePolynomial") + public inline fun NumberedPolynomial.substitute(argument: Map>): NumberedPolynomial = this.substitute(ring, argument) + + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedPolynomial.asFunction(): (Map) -> NumberedPolynomial = { this.substitute(ring, it) } + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedPolynomial.asFunctionOnConstants(): (Map) -> NumberedPolynomial = { this.substitute(ring, it) } + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedPolynomial.asFunctionOnPolynomials(): (Map>) -> NumberedPolynomial = { this.substitute(ring, it) } + + @Suppress("NOTHING_TO_INLINE") + public inline operator fun NumberedPolynomial.invoke(argument: Map): NumberedPolynomial = this.substitute(ring, argument) + @Suppress("NOTHING_TO_INLINE") + @JvmName("invokePolynomial") + public inline operator fun NumberedPolynomial.invoke(argument: Map>): NumberedPolynomial = this.substitute(ring, argument) + // endregion + + // region Legacy + @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") + override inline fun add(left: NumberedPolynomial, right: NumberedPolynomial): NumberedPolynomial = left + right + @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") + override inline fun multiply(left: NumberedPolynomial, right: NumberedPolynomial): NumberedPolynomial = left * right + // endregion + + // region Utilities + // TODO: Move to region internal utilities with context receiver + internal fun MutableMap, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : MutableMap, C> { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + block() + for ((degs, c) in this) if (c.isZero()) this.remove(degs) + return this + } + internal fun Map, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : Map, C> = + toMutableMap().applyAndRemoveZeros(block) + @OptIn(ExperimentalTypeInference::class) + internal fun buildCoefficients(@BuilderInference builderAction: MutableMap, C>.() -> Unit): Map, C> { + contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } + return buildMap { + builderAction() + for ((degs, c) in this) if (c.isZero()) this.remove(degs) + } + } + // endregion +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 30280a396..99d6b0659 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -5,43 +5,38 @@ package space.kscience.kmath.functions -import space.kscience.kmath.functions.AbstractPolynomialSpace.Companion.optimizedAddMultiplied -import space.kscience.kmath.functions.AbstractPolynomialSpace.Companion.optimizedMultiply import space.kscience.kmath.operations.* import kotlin.jvm.JvmName import kotlin.math.max import kotlin.math.min /** - * Polynomial coefficients model without fixation on specific context they are applied to. + * Polynomial model without fixation on specific context they are applied to. * * @param coefficients constant is the leftmost coefficient. */ public class Polynomial(public val coefficients: List) : AbstractPolynomial { override fun toString(): String = "Polynomial$coefficients" - -// public companion object { -// /** -// * Default name of variables used in string representations. -// * -// * @see Polynomial.toString -// */ -// public var defaultVariableName: String = "x" -// -// /** -// * Represents result of division with remainder. -// */ -// public data class DividingResult( -// val quotient: Polynomial, -// val reminder: Polynomial -// ) -// } } +// region Internal utilities + /** * Represents internal [Polynomial] errors. */ -internal class PolynomialError(message: String): Error(message) +internal class PolynomialError : Error { + constructor(): super() + constructor(message: String): super(message) + constructor(message: String?, cause: Throwable?): super(message, cause) + constructor(cause: Throwable?): super(cause) +} + +/** + * Throws an [PolynomialError] with the given [message]. + */ +internal fun polynomialError(message: Any): Nothing = throw PolynomialError(message.toString()) + +// endregion // region Constructors and converters @@ -66,16 +61,16 @@ public fun T.asPolynomial() : Polynomial = Polynomial(listOf(this)) // endregion /** - * Space of polynomials constructed over ring. + * Space of univariate 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]. */ -@Suppress("INAPPLICABLE_JVM_NAME") // KT-31420 +@Suppress("INAPPLICABLE_JVM_NAME") // TODO: KT-31420 public open class PolynomialSpace>( public val ring: A, -) : AbstractPolynomialSpace>{ +) : AbstractPolynomialSpace> { // region Constant-integer relation @JvmName("constantIntPlus") public override operator fun C.plus(other: Int): C = ring { optimizedAddMultiplied(this@plus, one, other) } @@ -102,8 +97,14 @@ public open class PolynomialSpace>( coefficients .toMutableList() .apply { - if (isEmpty()) this[0] = ring.zero + other - else this[0] = this[0]!! + other + val result = getOrElse(0) { ring.zero } + other + val isResultZero = result.isZero() + + when { + size == 0 && !isResultZero -> add(result) + size > 1 || !isResultZero -> this[0] = result + else -> clear() + } } ) public override operator fun Polynomial.minus(other: Int): Polynomial = @@ -113,8 +114,14 @@ public open class PolynomialSpace>( coefficients .toMutableList() .apply { - if (isEmpty()) this[0] = ring.zero - other - else this[0] = this[0]!! - other + val result = getOrElse(0) { ring.zero } - other + val isResultZero = result.isZero() + + when { + size == 0 && !isResultZero -> add(result) + size > 1 || !isResultZero -> this[0] = result + else -> clear() + } } ) public override operator fun Polynomial.times(other: Int): Polynomial = @@ -134,8 +141,14 @@ public open class PolynomialSpace>( other.coefficients .toMutableList() .apply { - if (isEmpty()) this[0] = ring.zero + this@plus - else this[0] = this[0]!! + this@plus + val result = this@plus + getOrElse(0) { ring.zero } + val isResultZero = result.isZero() + + when { + size == 0 && !isResultZero -> add(result) + size > 1 || !isResultZero -> this[0] = result + else -> clear() + } } ) public override operator fun Int.minus(other: Polynomial): Polynomial = @@ -145,8 +158,16 @@ public open class PolynomialSpace>( other.coefficients .toMutableList() .apply { - if (isEmpty()) this[0] = ring.zero - this@minus - else this[0] = this[0]!! - this@minus + forEachIndexed { index, c -> if (index != 0) this[index] = -c } + + val result = this@minus - getOrElse(0) { ring.zero } + val isResultZero = result.isZero() + + when { + size == 0 && !isResultZero -> add(result) + size > 1 || !isResultZero -> this[0] = result + else -> clear() + } } ) public override operator fun Int.times(other: Polynomial): Polynomial = @@ -183,12 +204,20 @@ public open class PolynomialSpace>( // region Constant-polynomial relation public override operator fun C.plus(other: Polynomial): Polynomial = - with(other.coefficients) { + if (this.isZero()) other + else with(other.coefficients) { if (isEmpty()) Polynomial(listOf(this@plus)) else Polynomial( toMutableList() .apply { - this[0] += this@plus + val result = if (size == 0) this@plus else this@plus + get(0) + val isResultZero = result.isZero() + + when { + size == 0 && !isResultZero -> add(result) + size > 1 || !isResultZero -> this[0] = result + else -> clear() + } } ) } @@ -196,12 +225,22 @@ public open class PolynomialSpace>( // listOf(coefficients[0] + other) + coefficients.subList(1, degree + 1) // ) public override operator fun C.minus(other: Polynomial): Polynomial = - with(other.coefficients) { + if (this.isZero()) other + else with(other.coefficients) { if (isEmpty()) Polynomial(listOf(-this@minus)) else Polynomial( toMutableList() .apply { - this[0] -= this@minus + forEachIndexed { index, c -> if (index != 0) this[index] = -c } + + val result = if (size == 0) this@minus else this@minus - get(0) + val isResultZero = result.isZero() + + when { + size == 0 && !isResultZero -> add(result) + size > 1 || !isResultZero -> this[0] = result + else -> clear() + } } ) } @@ -209,9 +248,10 @@ public open class PolynomialSpace>( // listOf(coefficients[0] + other) + coefficients.subList(1, degree + 1) // ) public override operator fun C.times(other: Polynomial): Polynomial = - Polynomial( + if (this.isZero()) other + else Polynomial( other.coefficients -// .subList(0, other.degree + 1) + .subList(0, other.degree + 1) .map { it * this } ) // endregion @@ -224,7 +264,14 @@ public open class PolynomialSpace>( else Polynomial( toMutableList() .apply { - this[0] += other + val result = if (size == 0) other else get(0) + other + val isResultZero = result.isZero() + + when { + size == 0 && !isResultZero -> add(result) + size > 1 || !isResultZero -> this[0] = result + else -> clear() + } } ) } @@ -232,12 +279,20 @@ public open class PolynomialSpace>( // listOf(coefficients[0] + other) + coefficients.subList(1, degree + 1) // ) public override operator fun Polynomial.minus(other: C): Polynomial = - with(coefficients) { + if (other.isZero()) this + else with(coefficients) { if (isEmpty()) Polynomial(listOf(other)) else Polynomial( toMutableList() .apply { - this[0] -= other + val result = if (size == 0) other else get(0) - other + val isResultZero = result.isZero() + + when { + size == 0 && !isResultZero -> add(result) + size > 1 || !isResultZero -> this[0] = result + else -> clear() + } } ) } @@ -245,9 +300,10 @@ public open class PolynomialSpace>( // listOf(coefficients[0] - other) + coefficients.subList(1, degree + 1) // ) public override operator fun Polynomial.times(other: C): Polynomial = - Polynomial( + if (other.isZero()) this + else Polynomial( coefficients -// .subList(0, degree + 1) + .subList(0, degree + 1) .map { it * other } ) // endregion @@ -283,8 +339,8 @@ public open class PolynomialSpace>( val thisDegree = degree val otherDegree = other.degree return when { - thisDegree == -1 -> this - otherDegree == -1 -> other + thisDegree == -1 -> zero + otherDegree == -1 -> zero else -> Polynomial( (0..(thisDegree + otherDegree)) @@ -293,6 +349,7 @@ public open class PolynomialSpace>( .map { coefficients[it] * other.coefficients[d - it] } .reduce { acc, rational -> acc + rational } } + .run { subList(0, indexOfLast { it.isNotZero() } + 1) } ) } } @@ -321,8 +378,8 @@ public open class PolynomialSpace>( } // endregion - // Not sure is it necessary... // region Polynomial properties + public override val Polynomial.degree: Int get() = coefficients.indexOfLast { it != ring.zero } public override fun Polynomial.asConstantOrNull(): C? = @@ -354,8 +411,8 @@ public open class PolynomialSpace>( public inline operator fun Polynomial.invoke(argument: C): C = this.substitute(ring, argument) @Suppress("NOTHING_TO_INLINE") public inline operator fun Polynomial.invoke(argument: Polynomial): Polynomial = this.substitute(ring, argument) - // endregion + // endregion } /** diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Variable.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Variable.kt new file mode 100644 index 000000000..410604fd3 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Variable.kt @@ -0,0 +1,38 @@ +package space.kscience.kmath.functions + +import kotlin.reflect.KProperty + + +/** + * Represents class of labeled variables like usual + * `x`, `y`, `z`, `a`, `b`, `n`, `m`, etc. + * + * Variables does not contain any information about field (or ring, ets.) they are considered in + * and therefore about coefficient. + * + * @property name Is the label or name of variable. For `x` it is `"x"`, for `n` – `"n"`, etc. + */ +public data class Variable (val name: String) : Comparable { + /** + * Represents the variable as a string. + * + * @return Only name of the variable. + */ + override fun toString(): String = name + /** + * Compares two variables. + * Comparison is realised by comparison of variables' names. + * + * Used in [LabeledPolynomial] and [LabeledRationalFunction] to sort monomials in + * [LabeledPolynomial.toString] and [LabeledRationalFunction.toString] in lexicographic order. + * + * @see Comparable.compareTo + * @sample LabeledPolynomial.monomialComparator + * @return Only name of the variable. + */ + override fun compareTo(other: Variable): Int = name.compareTo(other.name) + + public companion object { + public operator fun getValue(thisRef: Any?, property: KProperty<*>) : Variable = Variable(property.name) + } +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt new file mode 100644 index 000000000..9e5043b8c --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.Group + + +// TODO: All of this should be moved to algebraic structures' place for utilities +// TODO: Move receiver to context receiver +/** + * Multiplication of element and integer. + * + * @receiver the multiplicand. + * @param other the multiplier. + * @return the difference. + */ +internal tailrec fun Group.optimizedMultiply(arg: C, other: Int): C = + when { + other == 0 -> zero + other == 1 -> arg + other == -1 -> -arg + other % 2 == 0 -> optimizedMultiply(arg + arg, other / 2) + other % 2 == 1 -> optimizedAddMultiplied(arg, arg + arg, other / 2) + other % 2 == -1 -> optimizedAddMultiplied(-arg, arg + arg, other / 2) + else -> error("Error in multiplication group instant by integer: got reminder by division by 2 different from 0, 1 and -1") + } + +// TODO: Move receiver to context receiver +/** + * Adds product of [arg] and [multiplier] to [base]. + * + * @receiver the algebra to provide multiplication. + * @param base the augend. + * @param arg the multiplicand. + * @param multiplier the multiplier. + * @return sum of the augend [base] and product of the multiplicand [arg] and the multiplier [multiplier]. + * @author Gleb Minaev + */ +internal tailrec fun Group.optimizedAddMultiplied(base: C, arg: C, multiplier: Int): C = + when { + multiplier == 0 -> base + multiplier == 1 -> base + arg + multiplier == -1 -> base - arg + multiplier % 2 == 0 -> optimizedAddMultiplied(base, arg + arg, multiplier / 2) + multiplier % 2 == 1 -> optimizedAddMultiplied(base + arg, arg + arg, multiplier / 2) + multiplier % 2 == -1 -> optimizedAddMultiplied(base + arg, arg + arg, multiplier / 2) + else -> error("Error in multiplication group instant by integer: got reminder by division by 2 different from 0, 1 and -1") + } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt new file mode 100644 index 000000000..62ac31b64 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt @@ -0,0 +1,490 @@ +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.* +import kotlin.contracts.* + + +// TODO: Docs + +// region Sort of legacy + +//// region Constants +// +//// TODO: Reuse underlying ring extensions +// +//context(LabeledPolynomialSpace) +//@Suppress("NOTHING_TO_INLINE") +//fun > numberConstant(value: Int): C = ring { number(value) } +// +//context(LabeledPolynomialSpace) +//fun > power(arg: C, pow: UInt): C = ring { power(arg, pow) } +// +//context(LabeledPolynomialSpace) +//fun > multiplyWithPower(base: C, arg: C, pow: UInt): C = ring { multiplyWithPower(base, arg, pow) } +// +//// endregion + +//// region Variables +// +//context(LabeledPolynomialSpace) +//fun > power(arg: Variable, pow: UInt): LabeledPolynomial = +// if (pow == 0U) one +// else LabeledPolynomial(mapOf( +// mapOf(arg to pow) to ring.one +// )) +// +//// endregion + +//// region Polynomials +// +//context(LabeledPolynomialSpace) +//fun > number(value: Int): LabeledPolynomial = ring { LabeledPolynomial(mapOf(emptyMap() to number(value))) } +// +//context(LabeledPolynomialSpace) +//fun > multiplyWithPower(base: LabeledPolynomial, arg: LabeledPolynomial, pow: UInt): LabeledPolynomial = +// when { +// arg.isZero() && pow > 0U -> base +// arg.isOne() -> base +// arg.isMinusOne() -> if (pow % 2U == 0U) base else -base +// else -> multiplyWithPowerInternalLogic(base, arg, pow) +// } +// +//// Trivial but slow as duck +//context(LabeledPolynomialSpace) +//internal tailrec fun > multiplyWithPowerInternalLogic(base: LabeledPolynomial, arg: LabeledPolynomial, exponent: UInt): LabeledPolynomial = +// when { +// exponent == 0U -> base +// exponent == 1U -> base * arg +// exponent % 2U == 0U -> multiplyWithPowerInternalLogic(base, arg * arg, exponent / 2U) +// exponent % 2U == 1U -> multiplyWithPowerInternalLogic(base * arg, arg * arg, exponent / 2U) +// else -> error("Error in raising ring instant by unsigned integer: got reminder by division by 2 different from 0 and 1") +// } +// +//// endregion + +// endregion + +// region Utilities + +// TODO: Docs +@OptIn(ExperimentalContracts::class) +public inline fun , R> A.labeledPolynomial(block: LabeledPolynomialSpace.() -> R): R { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return LabeledPolynomialSpace(this).block() +} + +// endregion + +//// region String representations +// +///** +// * Represents the polynomial as a [String] with names of variables substituted with names from [names]. +// * Consider that monomials are sorted in lexicographic order. +// */ +//context(LabeledPolynomialSpace) +//fun > LabeledPolynomial.represent(names: Map = emptyMap()): String = +// coefficients.entries +// .sortedWith { o1, o2 -> LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } +// .asSequence() +// .map { (degs, t) -> +// if (degs.isEmpty()) "$t" +// else { +// when { +// t.isOne() -> "" +// t.isMinusOne() -> "-" +// else -> "$t " +// } + +// degs +// .toSortedMap() +// .filter { it.value > 0U } +// .map { (variable, deg) -> +// val variableName = names.getOrDefault(variable, variable.toString()) +// when (deg) { +// 1U -> variableName +// else -> "$variableName^$deg" +// } +// } +// .joinToString(separator = " ") { it } +// } +// } +// .joinToString(separator = " + ") { it } +// .ifEmpty { "0" } +// +///** +// * Represents the polynomial as a [String] naming variables by [namer]. +// * Consider that monomials are sorted in lexicographic order. +// */ +//context(LabeledPolynomialSpace) +//fun > LabeledPolynomial.represent(namer: (Variable) -> String): String = +// coefficients.entries +// .sortedWith { o1, o2 -> LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } +// .asSequence() +// .map { (degs, t) -> +// if (degs.isEmpty()) "$t" +// else { +// when { +// t.isOne() -> "" +// t.isMinusOne() -> "-" +// else -> "$t " +// } + +// degs +// .toSortedMap() +// .filter { it.value > 0U } +// .map { (variable, deg) -> +// when (deg) { +// 1U -> namer(variable) +// else -> "${namer(variable)}^$deg" +// } +// } +// .joinToString(separator = " ") { it } +// } +// } +// .joinToString(separator = " + ") { it } +// .ifEmpty { "0" } +// +///** +// * Represents the polynomial as a [String] with names of variables substituted with names from [names] and with +// * brackets around the string if needed (i.e. when there are at least two addends in the representation). +// * Consider that monomials are sorted in lexicographic order. +// */ +//context(LabeledPolynomialSpace) +//fun > LabeledPolynomial.representWithBrackets(names: Map = emptyMap()): String = +// with(represent(names)) { if (coefficients.count() == 1) this else "($this)" } +// +///** +// * Represents the polynomial as a [String] naming variables by [namer] and with brackets around the string if needed +// * (i.e. when there are at least two addends in the representation). +// * Consider that monomials are sorted in lexicographic order. +// */ +//context(LabeledPolynomialSpace) +//fun > LabeledPolynomial.representWithBrackets(namer: (Variable) -> String): String = +// with(represent(namer)) { if (coefficients.count() == 1) this else "($this)" } +// +///** +// * Represents the polynomial as a [String] with names of variables substituted with names from [names]. +// * Consider that monomials are sorted in **reversed** lexicographic order. +// */ +//context(LabeledPolynomialSpace) +//fun > LabeledPolynomial.representReversed(names: Map = emptyMap()): String = +// coefficients.entries +// .sortedWith { o1, o2 -> -LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } +// .asSequence() +// .map { (degs, t) -> +// if (degs.isEmpty()) "$t" +// else { +// when { +// t.isOne() -> "" +// t.isMinusOne() -> "-" +// else -> "$t " +// } + +// degs +// .toSortedMap() +// .filter { it.value > 0U } +// .map { (variable, deg) -> +// val variableName = names.getOrDefault(variable, variable.toString()) +// when (deg) { +// 1U -> variableName +// else -> "$variableName^$deg" +// } +// } +// .joinToString(separator = " ") { it } +// } +// } +// .joinToString(separator = " + ") { it } +// .ifEmpty { "0" } +// +///** +// * Represents the polynomial as a [String] naming variables by [namer]. +// * Consider that monomials are sorted in **reversed** lexicographic order. +// */ +//context(LabeledPolynomialSpace) +//fun > LabeledPolynomial.representReversed(namer: (Variable) -> String): String = +// coefficients.entries +// .sortedWith { o1, o2 -> -LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } +// .asSequence() +// .map { (degs, t) -> +// if (degs.isEmpty()) "$t" +// else { +// when { +// t.isOne() -> "" +// t.isMinusOne() -> "-" +// else -> "$t " +// } + +// degs +// .toSortedMap() +// .filter { it.value > 0U } +// .map { (variable, deg) -> +// when (deg) { +// 1U -> namer(variable) +// else -> "${namer(variable)}^$deg" +// } +// } +// .joinToString(separator = " ") { it } +// } +// } +// .joinToString(separator = " + ") { it } +// .ifEmpty { "0" } +// +///** +// * Represents the polynomial as a [String] with names of variables substituted with names from [names] and with +// * brackets around the string if needed (i.e. when there are at least two addends in the representation). +// * Consider that monomials are sorted in **reversed** lexicographic order. +// */ +//context(LabeledPolynomialSpace) +//fun > LabeledPolynomial.representReversedWithBrackets(names: Map = emptyMap()): String = +// with(representReversed(names)) { if (coefficients.count() == 1) this else "($this)" } +// +///** +// * Represents the polynomial as a [String] naming variables by [namer] and with brackets around the string if needed +// * (i.e. when there are at least two addends in the representation). +// * Consider that monomials are sorted in **reversed** lexicographic order. +// */ +//context(LabeledPolynomialSpace) +//fun > LabeledPolynomial.representReversedWithBrackets(namer: (Variable) -> String): String = +// with(representReversed(namer)) { if (coefficients.count() == 1) this else "($this)" } +// +//// endregion + +// region Operator extensions + +//// region Field case +// +//operator fun > Polynomial.div(other: Polynomial): Polynomial { +// if (other.isZero()) throw ArithmeticException("/ by zero") +// if (isZero()) return this +// +// fun Map, T>.leadingTerm() = +// this +// .asSequence() +// .map { Pair(it.key, it.value) } +// .reduce { (accDegs, accC), (listDegs, listC) -> +// for (i in 0..accDegs.lastIndex) { +// if (accDegs[i] > listDegs.getOrElse(i) { 0 }) return@reduce accDegs to accC +// if (accDegs[i] < listDegs.getOrElse(i) { 0 }) return@reduce listDegs to listC +// } +// if (accDegs.size < listDegs.size) listDegs to listC else accDegs to accC +// } +// +// var thisCoefficients = coefficients.toMutableMap() +// val otherCoefficients = other.coefficients +// val quotientCoefficients = HashMap, T>() +// +// var (thisLeadingTermDegs, thisLeadingTermC) = thisCoefficients.leadingTerm() +// val (otherLeadingTermDegs, otherLeadingTermC) = otherCoefficients.leadingTerm() +// +// while ( +// thisLeadingTermDegs.size >= otherLeadingTermDegs.size && +// (0..otherLeadingTermDegs.lastIndex).all { thisLeadingTermDegs[it] >= otherLeadingTermDegs[it] } +// ) { +// val multiplierDegs = +// thisLeadingTermDegs +// .mapIndexed { index, deg -> deg - otherLeadingTermDegs.getOrElse(index) { 0 } } +// .cleanUp() +// val multiplierC = thisLeadingTermC / otherLeadingTermC +// +// quotientCoefficients[multiplierDegs] = multiplierC +// +// for ((degs, t) in otherCoefficients) { +// val productDegs = +// (0..max(degs.lastIndex, multiplierDegs.lastIndex)) +// .map { degs.getOrElse(it) { 0 } + multiplierDegs.getOrElse(it) { 0 } } +// .cleanUp() +// val productC = t * multiplierC +// thisCoefficients[productDegs] = +// if (productDegs in thisCoefficients) thisCoefficients[productDegs]!! - productC else -productC +// } +// +// thisCoefficients = thisCoefficients.filterValues { it.isNotZero() }.toMutableMap() +// +// if (thisCoefficients.isEmpty()) +// return Polynomial(quotientCoefficients, toCheckInput = false) +// +// val t = thisCoefficients.leadingTerm() +// thisLeadingTermDegs = t.first +// thisLeadingTermC = t.second +// } +// +// return Polynomial(quotientCoefficients, toCheckInput = false) +//} +// +//operator fun > Polynomial.div(other: T): Polynomial = +// if (other.isZero()) throw ArithmeticException("/ by zero") +// else +// Polynomial( +// coefficients +// .mapValues { it.value / other }, +// toCheckInput = false +// ) +// +//operator fun > Polynomial.rem(other: Polynomial): Polynomial { +// if (other.isZero()) throw ArithmeticException("/ by zero") +// if (isZero()) return this +// +// fun Map, T>.leadingTerm() = +// this +// .asSequence() +// .map { Pair(it.key, it.value) } +// .reduce { (accDegs, accC), (listDegs, listC) -> +// for (i in 0..accDegs.lastIndex) { +// if (accDegs[i] > listDegs.getOrElse(i) { 0 }) return@reduce accDegs to accC +// if (accDegs[i] < listDegs.getOrElse(i) { 0 }) return@reduce listDegs to listC +// } +// if (accDegs.size < listDegs.size) listDegs to listC else accDegs to accC +// } +// +// var thisCoefficients = coefficients.toMutableMap() +// val otherCoefficients = other.coefficients +// +// var (thisLeadingTermDegs, thisLeadingTermC) = thisCoefficients.leadingTerm() +// val (otherLeadingTermDegs, otherLeadingTermC) = otherCoefficients.leadingTerm() +// +// while ( +// thisLeadingTermDegs.size >= otherLeadingTermDegs.size && +// (0..otherLeadingTermDegs.lastIndex).all { thisLeadingTermDegs[it] >= otherLeadingTermDegs[it] } +// ) { +// val multiplierDegs = +// thisLeadingTermDegs +// .mapIndexed { index, deg -> deg - otherLeadingTermDegs.getOrElse(index) { 0 } } +// .cleanUp() +// val multiplierC = thisLeadingTermC / otherLeadingTermC +// +// for ((degs, t) in otherCoefficients) { +// val productDegs = +// (0..max(degs.lastIndex, multiplierDegs.lastIndex)) +// .map { degs.getOrElse(it) { 0 } + multiplierDegs.getOrElse(it) { 0 } } +// .cleanUp() +// val productC = t * multiplierC +// thisCoefficients[productDegs] = +// if (productDegs in thisCoefficients) thisCoefficients[productDegs]!! - productC else -productC +// } +// +// thisCoefficients = thisCoefficients.filterValues { it.isNotZero() }.toMutableMap() +// +// if (thisCoefficients.isEmpty()) +// return Polynomial(thisCoefficients, toCheckInput = false) +// +// val t = thisCoefficients.leadingTerm() +// thisLeadingTermDegs = t.first +// thisLeadingTermC = t.second +// } +// +// return Polynomial(thisCoefficients, toCheckInput = false) +//} +// +//infix fun > Polynomial.divrem(other: Polynomial): Polynomial.Companion.DividingResult { +// if (other.isZero()) throw ArithmeticException("/ by zero") +// if (isZero()) return Polynomial.Companion.DividingResult(this, this) +// +// fun Map, T>.leadingTerm() = +// this +// .asSequence() +// .map { Pair(it.key, it.value) } +// .reduce { (accDegs, accC), (listDegs, listC) -> +// for (i in 0..accDegs.lastIndex) { +// if (accDegs[i] > listDegs.getOrElse(i) { 0 }) return@reduce accDegs to accC +// if (accDegs[i] < listDegs.getOrElse(i) { 0 }) return@reduce listDegs to listC +// } +// if (accDegs.size < listDegs.size) listDegs to listC else accDegs to accC +// } +// +// var thisCoefficients = coefficients.toMutableMap() +// val otherCoefficients = other.coefficients +// val quotientCoefficients = HashMap, T>() +// +// var (thisLeadingTermDegs, thisLeadingTermC) = thisCoefficients.leadingTerm() +// val (otherLeadingTermDegs, otherLeadingTermC) = otherCoefficients.leadingTerm() +// +// while ( +// thisLeadingTermDegs.size >= otherLeadingTermDegs.size && +// (0..otherLeadingTermDegs.lastIndex).all { thisLeadingTermDegs[it] >= otherLeadingTermDegs[it] } +// ) { +// val multiplierDegs = +// thisLeadingTermDegs +// .mapIndexed { index, deg -> deg - otherLeadingTermDegs.getOrElse(index) { 0 } } +// .cleanUp() +// val multiplierC = thisLeadingTermC / otherLeadingTermC +// +// quotientCoefficients[multiplierDegs] = multiplierC +// +// for ((degs, t) in otherCoefficients) { +// val productDegs = +// (0..max(degs.lastIndex, multiplierDegs.lastIndex)) +// .map { degs.getOrElse(it) { 0 } + multiplierDegs.getOrElse(it) { 0 } } +// .cleanUp() +// val productC = t * multiplierC +// thisCoefficients[productDegs] = +// if (productDegs in thisCoefficients) thisCoefficients[productDegs]!! - productC else -productC +// } +// +// thisCoefficients = thisCoefficients.filterValues { it.isNotZero() }.toMutableMap() +// +// if (thisCoefficients.isEmpty()) +// return Polynomial.Companion.DividingResult( +// Polynomial(quotientCoefficients, toCheckInput = false), +// Polynomial(thisCoefficients, toCheckInput = false) +// ) +// +// val t = thisCoefficients.leadingTerm() +// thisLeadingTermDegs = t.first +// thisLeadingTermC = t.second +// } +// +// return Polynomial.Companion.DividingResult( +// Polynomial(quotientCoefficients, toCheckInput = false), +// Polynomial(thisCoefficients, toCheckInput = false) +// ) +//} +// +//// endregion + +// endregion + +//// region Polynomial substitution and functional representation +// +//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 = degs.entries.asSequence().filter { it.key in args }.fold(c) { acc, (variable, deg) -> +// multiplyWithPower(acc, args[variable]!!, deg) +// } +// this[newDegs] = if (newDegs in this) this[newDegs]!! + newC else newC +// } +// } +// ) +//} +// +//// TODO: Replace with optimisation: the [result] may be unboxed, and all operations may be performed as soon as +//// possible on it +//@JvmName("substitutePolynomial") +//fun LabeledPolynomial.substitute(ring: Ring, arg: Map>) : LabeledPolynomial = +// ring.labeledPolynomial { +// if (coefficients.isEmpty()) return zero +// coefficients +// .asSequence() +// .map { (degs, c) -> +// degs.entries +// .asSequence() +// .filter { it.key in arg } +// .fold(LabeledPolynomial(mapOf(degs.filterKeys { it !in arg } to c))) { acc, (index, deg) -> +// multiplyWithPower(acc, arg[index]!!, deg) +// } +// } +// .reduce { acc, polynomial -> acc + polynomial } // TODO: Rewrite. Might be slow. +// } +// +//// TODO: Substitute rational function +// +//fun > LabeledPolynomial.asFunctionOver(ring: A): (Map) -> LabeledPolynomial = +// { substitute(ring, it) } +// +//fun > LabeledPolynomial.asPolynomialFunctionOver(ring: A): (Map>) -> LabeledPolynomial = +// { substitute(ring, it) } +// +//// endregion + +//// region Algebraic derivative and antiderivative +//// TODO +//// endregion \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt new file mode 100644 index 000000000..d4053442d --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt @@ -0,0 +1,605 @@ +package space.kscience.kmath.functions + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.* +import kotlin.contracts.* +import kotlin.jvm.JvmName + + +// TODO: Docs + +// region Sort of legacy + +//// region Constants +// +//// TODO: Reuse underlying ring extensions +// +//context(NumberedPolynomialSpace) +//@Suppress("NOTHING_TO_INLINE") +//public fun > numberConstant(value: Int): C = ring { number(value) } +// +//context(NumberedPolynomialSpace) +//public fun > multiplyWithPower(base: C, arg: C, pow: UInt): C = ring { multiplyWithPower(base, arg, pow) } +// +//// endregion + +//// region Polynomials +// +//context(NumberedPolynomialSpace) +//public fun > number(value: Int): NumberedPolynomial = ring { NumberedPolynomial(mapOf(emptyList() to number(value))) } +// +//context(NumberedPolynomialSpace) +//public fun > multiplyWithPower(base: NumberedPolynomial, arg: NumberedPolynomial, pow: UInt): NumberedPolynomial = +// when { +// arg.isZero() && pow > 0U -> base +// arg.isOne() -> base +// arg.isMinusOne() -> if (pow % 2U == 0U) base else -base +// else -> multiplyWithPowerInternalLogic(base, arg, pow) +// } +// +//// Trivial but slow as duck +//context(NumberedPolynomialSpace) +//internal tailrec fun > multiplyWithPowerInternalLogic(base: NumberedPolynomial, arg: NumberedPolynomial, exponent: UInt): NumberedPolynomial = +// when { +// exponent == 0U -> base +// exponent == 1U -> base * arg +// exponent % 2U == 0U -> multiplyWithPowerInternalLogic(base, arg * arg, exponent / 2U) +// exponent % 2U == 1U -> multiplyWithPowerInternalLogic(base * arg, arg * arg, exponent / 2U) +// else -> error("Error in raising ring instant by unsigned integer: got reminder by division by 2 different from 0 and 1") +// } +// +//// endregion + +// endregion + +// region Utilities + +// TODO: Docs +@OptIn(ExperimentalContracts::class) +public inline fun , R> A.numberedPolynomial(block: NumberedPolynomialSpace.() -> R): R { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return NumberedPolynomialSpace(this).block() +} + +// endregion + +//// region String representations +// +///** +// * Represents the polynomial as a [String] where name of variable with index `i` is [withVariableName] + `"_${i+1}"`. +// * Consider that monomials are sorted in lexicographic order. +// */ +//context(NumberedPolynomialSpace) +//public fun > NumberedPolynomial.represent(withVariableName: String = NumberedPolynomial.defaultVariableName): String = +// coefficients.entries +// .sortedWith { o1, o2 -> NumberedPolynomial.monomialComparator.compare(o1.key, o2.key) } +// .asSequence() +// .map { (degs, t) -> +// if (degs.isEmpty()) "$t" +// else { +// when { +// t.isOne() -> "" +// t.isMinusOne() -> "-" +// else -> "$t " +// } + +// degs +// .mapIndexed { index, deg -> +// when (deg) { +// 0U -> "" +// 1U -> "${withVariableName}_${index+1}" +// else -> "${withVariableName}_${index+1}^$deg" +// } +// } +// .filter { it.isNotEmpty() } +// .joinToString(separator = " ") { it } +// } +// } +// .joinToString(separator = " + ") { it } +// .ifEmpty { "0" } +// +///** +// * Represents the polynomial as a [String] naming variables by [namer]. +// * Consider that monomials are sorted in lexicographic order. +// */ +//context(NumberedPolynomialSpace) +//public fun > NumberedPolynomial.represent(namer: (Int) -> String): String = +// coefficients.entries +// .sortedWith { o1, o2 -> NumberedPolynomial.monomialComparator.compare(o1.key, o2.key) } +// .asSequence() +// .map { (degs, t) -> +// if (degs.isEmpty()) "$t" +// else { +// when { +// t.isOne() -> "" +// t.isMinusOne() -> "-" +// else -> "$t " +// } + +// degs +// .mapIndexed { index, deg -> +// when (deg) { +// 0U -> "" +// 1U -> namer(index) +// else -> "${namer(index)}^$deg" +// } +// } +// .filter { it.isNotEmpty() } +// .joinToString(separator = " ") { it } +// } +// } +// .joinToString(separator = " + ") { it } +// .ifEmpty { "0" } +// +///** +// * Represents the polynomial as a [String] where name of variable with index `i` is [withVariableName] + `"_${i+1}"` +// * and with brackets around the string if needed (i.e. when there are at least two addends in the representation). +// * Consider that monomials are sorted in lexicographic order. +// */ +//context(NumberedPolynomialSpace) +//public fun > NumberedPolynomial.representWithBrackets(withVariableName: String = NumberedPolynomial.defaultVariableName): String = +// with(represent(withVariableName)) { if (coefficients.count() == 1) this else "($this)" } +// +///** +// * Represents the polynomial as a [String] naming variables by [namer] and with brackets around the string if needed +// * (i.e. when there are at least two addends in the representation). +// * Consider that monomials are sorted in lexicographic order. +// */ +//context(NumberedPolynomialSpace) +//public fun > NumberedPolynomial.representWithBrackets(namer: (Int) -> String): String = +// with(represent(namer)) { if (coefficients.count() == 1) this else "($this)" } +// +///** +// * Represents the polynomial as a [String] where name of variable with index `i` is [withVariableName] + `"_${i+1}"`. +// * Consider that monomials are sorted in **reversed** lexicographic order. +// */ +//context(NumberedPolynomialSpace) +//public fun > NumberedPolynomial.representReversed(withVariableName: String = NumberedPolynomial.defaultVariableName): String = +// coefficients.entries +// .sortedWith { o1, o2 -> -NumberedPolynomial.monomialComparator.compare(o1.key, o2.key) } +// .asSequence() +// .map { (degs, t) -> +// if (degs.isEmpty()) "$t" +// else { +// when { +// t.isOne() -> "" +// t.isMinusOne() -> "-" +// else -> "$t " +// } + +// degs +// .mapIndexed { index, deg -> +// when (deg) { +// 0U -> "" +// 1U -> "${withVariableName}_${index+1}" +// else -> "${withVariableName}_${index+1}^$deg" +// } +// } +// .filter { it.isNotEmpty() } +// .joinToString(separator = " ") { it } +// } +// } +// .joinToString(separator = " + ") { it } +// .ifEmpty { "0" } +// +///** +// * Represents the polynomial as a [String] naming variables by [namer]. +// * Consider that monomials are sorted in **reversed** lexicographic order. +// */ +//context(NumberedPolynomialSpace) +//public fun > NumberedPolynomial.representReversed(namer: (Int) -> String): String = +// coefficients.entries +// .sortedWith { o1, o2 -> -NumberedPolynomial.monomialComparator.compare(o1.key, o2.key) } +// .asSequence() +// .map { (degs, t) -> +// if (degs.isEmpty()) "$t" +// else { +// when { +// t.isOne() -> "" +// t.isMinusOne() -> "-" +// else -> "$t " +// } + +// degs +// .mapIndexed { index, deg -> +// when (deg) { +// 0U -> "" +// 1U -> namer(index) +// else -> "${namer(index)}^$deg" +// } +// } +// .filter { it.isNotEmpty() } +// .joinToString(separator = " ") { it } +// } +// } +// .joinToString(separator = " + ") { it } +// .ifEmpty { "0" } +// +///** +// * Represents the polynomial as a [String] where name of variable with index `i` is [withVariableName] + `"_${i+1}"` +// * and with brackets around the string if needed (i.e. when there are at least two addends in the representation). +// * Consider that monomials are sorted in **reversed** lexicographic order. +// */ +//context(NumberedPolynomialSpace) +//public fun > NumberedPolynomial.representReversedWithBrackets(withVariableName: String = NumberedPolynomial.defaultVariableName): String = +// with(representReversed(withVariableName)) { if (coefficients.count() == 1) this else "($this)" } +// +///** +// * Represents the polynomial as a [String] naming variables by [namer] and with brackets around the string if needed +// * (i.e. when there are at least two addends in the representation). +// * Consider that monomials are sorted in **reversed** lexicographic order. +// */ +//context(NumberedPolynomialSpace) +//public fun > NumberedPolynomial.representReversedWithBrackets(namer: (Int) -> String): String = +// with(representReversed(namer)) { if (coefficients.count() == 1) this else "($this)" } +// +//// endregion + +//// region Polynomial substitution and functional representation +// +//public fun NumberedPolynomial.substitute(ring: Ring, args: Map): NumberedPolynomial = ring { +// if (coefficients.isEmpty()) return this@substitute +// NumberedPolynomial( +// buildMap { +// coefficients.forEach { (degs, c) -> +// val newDegs = degs.mapIndexed { index, deg -> if (index in args) 0U else deg }.cleanUp() +// val newC = degs.foldIndexed(c) { index, acc, deg -> +// if (index in args) multiplyWithPower(acc, args[index]!!, deg) +// else acc +// } +// this[newDegs] = if (newDegs in this) this[newDegs]!! + newC else newC +// } +// } +// ) +//} +// +//// TODO: Replace with optimisation: the [result] may be unboxed, and all operations may be performed as soon as +//// possible on it +//@JvmName("substitutePolynomial") +//public fun NumberedPolynomial.substitute(ring: Ring, arg: Map>) : NumberedPolynomial = +// ring.numberedPolynomialSpace { +// if (coefficients.isEmpty()) return zero +// coefficients +// .asSequence() +// .map { (degs, c) -> +// degs.foldIndexed( +// NumberedPolynomial( +// degs.mapIndexed { index, deg -> if (index in arg) 0U else deg } to c +// ) +// ) { index, acc, deg -> if (index in arg) multiplyWithPower(acc, arg[index]!!, deg) else acc } +// } +// .reduce { acc, polynomial -> acc + polynomial } // TODO: Rewrite. Might be slow. +// } +// +//// TODO: Substitute rational function +// +//public fun > NumberedPolynomial.asFunctionOver(ring: A): (Map) -> NumberedPolynomial = +// { substitute(ring, it) } +// +//public fun > NumberedPolynomial.asPolynomialFunctionOver(ring: A): (Map>) -> NumberedPolynomial = +// { substitute(ring, it) } +// +//// endregion + +// region Operator extensions + +//// region Field case +// +//operator fun > Polynomial.div(other: Polynomial): Polynomial { +// if (other.isZero()) throw ArithmeticException("/ by zero") +// if (isZero()) return this +// +// fun Map, T>.leadingTerm() = +// this +// .asSequence() +// .map { Pair(it.key, it.value) } +// .reduce { (accDegs, accC), (listDegs, listC) -> +// for (i in 0..accDegs.lastIndex) { +// if (accDegs[i] > listDegs.getOrElse(i) { 0 }) return@reduce accDegs to accC +// if (accDegs[i] < listDegs.getOrElse(i) { 0 }) return@reduce listDegs to listC +// } +// if (accDegs.size < listDegs.size) listDegs to listC else accDegs to accC +// } +// +// var thisCoefficients = coefficients.toMutableMap() +// val otherCoefficients = other.coefficients +// val quotientCoefficients = HashMap, T>() +// +// var (thisLeadingTermDegs, thisLeadingTermC) = thisCoefficients.leadingTerm() +// val (otherLeadingTermDegs, otherLeadingTermC) = otherCoefficients.leadingTerm() +// +// while ( +// thisLeadingTermDegs.size >= otherLeadingTermDegs.size && +// (0..otherLeadingTermDegs.lastIndex).all { thisLeadingTermDegs[it] >= otherLeadingTermDegs[it] } +// ) { +// val multiplierDegs = +// thisLeadingTermDegs +// .mapIndexed { index, deg -> deg - otherLeadingTermDegs.getOrElse(index) { 0 } } +// .cleanUp() +// val multiplierC = thisLeadingTermC / otherLeadingTermC +// +// quotientCoefficients[multiplierDegs] = multiplierC +// +// for ((degs, t) in otherCoefficients) { +// val productDegs = +// (0..max(degs.lastIndex, multiplierDegs.lastIndex)) +// .map { degs.getOrElse(it) { 0 } + multiplierDegs.getOrElse(it) { 0 } } +// .cleanUp() +// val productC = t * multiplierC +// thisCoefficients[productDegs] = +// if (productDegs in thisCoefficients) thisCoefficients[productDegs]!! - productC else -productC +// } +// +// thisCoefficients = thisCoefficients.filterValues { it.isNotZero() }.toMutableMap() +// +// if (thisCoefficients.isEmpty()) +// return Polynomial(quotientCoefficients, toCheckInput = false) +// +// val t = thisCoefficients.leadingTerm() +// thisLeadingTermDegs = t.first +// thisLeadingTermC = t.second +// } +// +// return Polynomial(quotientCoefficients, toCheckInput = false) +//} +// +//operator fun > Polynomial.div(other: T): Polynomial = +// if (other.isZero()) throw ArithmeticException("/ by zero") +// else +// Polynomial( +// coefficients +// .mapValues { it.value / other }, +// toCheckInput = false +// ) +// +//operator fun > Polynomial.rem(other: Polynomial): Polynomial { +// if (other.isZero()) throw ArithmeticException("/ by zero") +// if (isZero()) return this +// +// fun Map, T>.leadingTerm() = +// this +// .asSequence() +// .map { Pair(it.key, it.value) } +// .reduce { (accDegs, accC), (listDegs, listC) -> +// for (i in 0..accDegs.lastIndex) { +// if (accDegs[i] > listDegs.getOrElse(i) { 0 }) return@reduce accDegs to accC +// if (accDegs[i] < listDegs.getOrElse(i) { 0 }) return@reduce listDegs to listC +// } +// if (accDegs.size < listDegs.size) listDegs to listC else accDegs to accC +// } +// +// var thisCoefficients = coefficients.toMutableMap() +// val otherCoefficients = other.coefficients +// +// var (thisLeadingTermDegs, thisLeadingTermC) = thisCoefficients.leadingTerm() +// val (otherLeadingTermDegs, otherLeadingTermC) = otherCoefficients.leadingTerm() +// +// while ( +// thisLeadingTermDegs.size >= otherLeadingTermDegs.size && +// (0..otherLeadingTermDegs.lastIndex).all { thisLeadingTermDegs[it] >= otherLeadingTermDegs[it] } +// ) { +// val multiplierDegs = +// thisLeadingTermDegs +// .mapIndexed { index, deg -> deg - otherLeadingTermDegs.getOrElse(index) { 0 } } +// .cleanUp() +// val multiplierC = thisLeadingTermC / otherLeadingTermC +// +// for ((degs, t) in otherCoefficients) { +// val productDegs = +// (0..max(degs.lastIndex, multiplierDegs.lastIndex)) +// .map { degs.getOrElse(it) { 0 } + multiplierDegs.getOrElse(it) { 0 } } +// .cleanUp() +// val productC = t * multiplierC +// thisCoefficients[productDegs] = +// if (productDegs in thisCoefficients) thisCoefficients[productDegs]!! - productC else -productC +// } +// +// thisCoefficients = thisCoefficients.filterValues { it.isNotZero() }.toMutableMap() +// +// if (thisCoefficients.isEmpty()) +// return Polynomial(thisCoefficients, toCheckInput = false) +// +// val t = thisCoefficients.leadingTerm() +// thisLeadingTermDegs = t.first +// thisLeadingTermC = t.second +// } +// +// return Polynomial(thisCoefficients, toCheckInput = false) +//} +// +//infix fun > Polynomial.divrem(other: Polynomial): Polynomial.Companion.DividingResult { +// if (other.isZero()) throw ArithmeticException("/ by zero") +// if (isZero()) return Polynomial.Companion.DividingResult(this, this) +// +// fun Map, T>.leadingTerm() = +// this +// .asSequence() +// .map { Pair(it.key, it.value) } +// .reduce { (accDegs, accC), (listDegs, listC) -> +// for (i in 0..accDegs.lastIndex) { +// if (accDegs[i] > listDegs.getOrElse(i) { 0 }) return@reduce accDegs to accC +// if (accDegs[i] < listDegs.getOrElse(i) { 0 }) return@reduce listDegs to listC +// } +// if (accDegs.size < listDegs.size) listDegs to listC else accDegs to accC +// } +// +// var thisCoefficients = coefficients.toMutableMap() +// val otherCoefficients = other.coefficients +// val quotientCoefficients = HashMap, T>() +// +// var (thisLeadingTermDegs, thisLeadingTermC) = thisCoefficients.leadingTerm() +// val (otherLeadingTermDegs, otherLeadingTermC) = otherCoefficients.leadingTerm() +// +// while ( +// thisLeadingTermDegs.size >= otherLeadingTermDegs.size && +// (0..otherLeadingTermDegs.lastIndex).all { thisLeadingTermDegs[it] >= otherLeadingTermDegs[it] } +// ) { +// val multiplierDegs = +// thisLeadingTermDegs +// .mapIndexed { index, deg -> deg - otherLeadingTermDegs.getOrElse(index) { 0 } } +// .cleanUp() +// val multiplierC = thisLeadingTermC / otherLeadingTermC +// +// quotientCoefficients[multiplierDegs] = multiplierC +// +// for ((degs, t) in otherCoefficients) { +// val productDegs = +// (0..max(degs.lastIndex, multiplierDegs.lastIndex)) +// .map { degs.getOrElse(it) { 0 } + multiplierDegs.getOrElse(it) { 0 } } +// .cleanUp() +// val productC = t * multiplierC +// thisCoefficients[productDegs] = +// if (productDegs in thisCoefficients) thisCoefficients[productDegs]!! - productC else -productC +// } +// +// thisCoefficients = thisCoefficients.filterValues { it.isNotZero() }.toMutableMap() +// +// if (thisCoefficients.isEmpty()) +// return Polynomial.Companion.DividingResult( +// Polynomial(quotientCoefficients, toCheckInput = false), +// Polynomial(thisCoefficients, toCheckInput = false) +// ) +// +// val t = thisCoefficients.leadingTerm() +// thisLeadingTermDegs = t.first +// thisLeadingTermC = t.second +// } +// +// return Polynomial.Companion.DividingResult( +// Polynomial(quotientCoefficients, toCheckInput = false), +// Polynomial(thisCoefficients, toCheckInput = false) +// ) +//} +// +//// endregion + +// endregion + +// region Polynomial substitution and functional representation + +// TODO: May be apply Horner's method too? +/** + * Evaluates the value of the given double polynomial for given double argument. + */ +public fun NumberedPolynomial.substitute(args: Map): NumberedPolynomial = Double.algebra { + val acc = LinkedHashMap, Double>(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, substitutor) -> + val deg = degs.getOrElse(variable) { 0u } + if (deg == 0u) product else product * substitutor.pow(deg.toInt()) + } + if (newDegs !in acc) acc[newDegs] = c + else acc[newDegs] = acc[newDegs]!! + c + } + return NumberedPolynomial(acc) +} + +/** + * Evaluates the value of the given polynomial for given argument. + * + * It is an implementation of [Horner's method](https://en.wikipedia.org/wiki/Horner%27s_method). + */ +public fun NumberedPolynomial.substitute(ring: Ring, args: Map): NumberedPolynomial = ring { + val acc = LinkedHashMap, C>(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, substitutor) -> + val deg = degs.getOrElse(variable) { 0u } + if (deg == 0u) product else product * power(substitutor, deg) + } + if (newDegs !in acc) acc[newDegs] = c + else acc[newDegs] = acc[newDegs]!! + c + } + return NumberedPolynomial(acc) +} + +// TODO: (Waiting for hero) Replace with optimisation: the [result] may be unboxed, and all operations may be performed +// as soon as possible on it +@JvmName("substitutePolynomial") +public fun NumberedPolynomial.substitute(ring: Ring, args: Map>) : NumberedPolynomial = TODO() /*ring.numberedPolynomial { + val acc = LinkedHashMap, NumberedPolynomial>(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.asNumberedPolynomial()) { product, (variable, substitutor) -> + val deg = degs.getOrElse(variable) { 0u } + if (deg == 0u) product else product * power(substitutor, deg) + } + if (newDegs !in acc) acc[newDegs] = c.asNumberedPolynomial() + else acc[newDegs] = acc[newDegs]!! + c + } +}*/ + +/** + * Represent the polynomial as a regular context-less function. + */ +public fun > NumberedPolynomial.asFunction(ring: A): (Map) -> NumberedPolynomial = { substitute(ring, it) } + +/** + * Represent the polynomial as a regular context-less function. + */ +public fun > NumberedPolynomial.asPolynomialFunctionOver(ring: A): (Map>) -> NumberedPolynomial = { substitute(ring, it) } + +// endregion + +// region Algebraic derivative and antiderivative + +/** + * Returns algebraic derivative of received polynomial. + */ +@UnstableKMathAPI +public fun NumberedPolynomial.derivativeBy( + algebra: A, + variable: Int, +): Polynomial where A : Ring, A : NumericAlgebra = algebra { + TODO() +} + +/** + * Returns algebraic derivative of received polynomial. + */ +@UnstableKMathAPI +public fun NumberedPolynomial.derivativeBy( + algebra: A, + variables: IntArray, +): Polynomial where A : Ring, A : NumericAlgebra = algebra { + TODO() +} + +/** + * Returns algebraic derivative of received polynomial. + */ +@UnstableKMathAPI +public fun NumberedPolynomial.derivativeBy( + algebra: A, + variables: Collection, +): Polynomial where A : Ring, A : NumericAlgebra = derivativeBy(algebra, variables.toIntArray()) + +/** + * Create a polynomial witch represents indefinite integral version of this polynomial + */ +@UnstableKMathAPI +public fun NumberedPolynomial.antiderivativeBy( + algebra: A, + variable: Int, +): Polynomial where A : Field, A : NumericAlgebra = algebra { + TODO() +} + +/** + * Create a polynomial witch represents indefinite integral version of this polynomial + */ +@UnstableKMathAPI +public fun NumberedPolynomial.antiderivativeBy( + algebra: A, + variables: IntArray, +): Polynomial where A : Field, A : NumericAlgebra = algebra { + TODO() +} + +/** + * Create a polynomial witch represents indefinite integral version of this polynomial + */ +@UnstableKMathAPI +public fun NumberedPolynomial.antiderivativeBy( + algebra: A, + variables: Collection, +): Polynomial where A : Field, A : NumericAlgebra = antiderivativeBy(algebra, variables.toIntArray()) + +// endregion \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt index 1a3eb7874..4d99b3a45 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt @@ -121,7 +121,7 @@ public fun Polynomial.antiderivative( ): Polynomial where A : Field, A : NumericAlgebra = algebra { val integratedCoefficients = buildList(coefficients.size + 1) { add(zero) - coefficients.forEachIndexed{ index, t -> add(t / (number(index) + one)) } + coefficients.forEachIndexed{ index, t -> add(t / number(index + 1)) } } Polynomial(integratedCoefficients) } @@ -136,4 +136,6 @@ public fun > Polynomial.integrate( ): C = algebra { val integral = antiderivative(algebra) integral.substitute(algebra, range.endInclusive) - integral.substitute(algebra, range.start) -} \ No newline at end of file +} + +// endregion \ No newline at end of file -- 2.34.1 From 191dd02e478787df7a50efb7b9568701ad243d01 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Thu, 3 Mar 2022 20:45:35 +0300 Subject: [PATCH 013/275] Restructured Polynomial --- .../kmath/functions/AbstractPolynomial.kt | 354 +++++++++++++++ .../kscience/kmath/functions/Piecewise.kt | 8 +- .../kscience/kmath/functions/Polynomial.kt | 425 ++++++++++++++---- .../kmath/functions/polynomialUtil.kt | 139 ++++++ .../kmath/integration/SplineIntegrator.kt | 3 +- .../kmath/interpolation/Interpolator.kt | 4 +- .../kmath/functions/PolynomialTest.kt | 11 +- 7 files changed, 845 insertions(+), 99 deletions(-) create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt new file mode 100644 index 000000000..f6a617656 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt @@ -0,0 +1,354 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.* +import kotlin.js.JsName +import kotlin.jvm.JvmName + + +/** + * Abstraction of polynomials. + */ +public interface AbstractPolynomial + +/** + * Abstraction of ring of polynomials of type [P] over ring of constants of type [C]. + */ +@Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") +public interface AbstractPolynomialSpace> : Ring

{ + // region Constant-integer relation + /** + * Returns sum of the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. + */ + @JvmName("constantIntPlus") + public operator fun C.plus(other: Int): C + /** + * Returns difference between the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. + */ + @JvmName("constantIntMinus") + public operator fun C.minus(other: Int): C + /** + * Returns product of the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + @JvmName("constantIntTimes") + public operator fun C.times(other: Int): C + // endregion + + // region Integer-constant relation + /** + * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. + */ + @JvmName("intConstantPlus") + public operator fun Int.plus(other: C): C + /** + * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. + */ + @JvmName("intConstantMinus") + public operator fun Int.minus(other: C): C + /** + * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + @JvmName("intConstantTimes") + public operator fun Int.times(other: C): C + // endregion + + // region Polynomial-integer relation + /** + * Returns sum of the constant and the integer represented as polynomial. + * + * The operation is equivalent to adding [other] copies of unit polynomial to [this]. + */ + public operator fun P.plus(other: Int): P = optimizedAddMultiplied(this, one, other) + /** + * Returns difference between the constant and the integer represented as polynomial. + * + * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. + */ + public operator fun P.minus(other: Int): P = optimizedAddMultiplied(this, one, -other) + /** + * Returns product of the constant and the integer represented as polynomial. + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + public operator fun P.times(other: Int): P = optimizedMultiply(this, other) + // endregion + + // region Integer-polynomial relation + /** + * Returns sum of the integer represented as polynomial and the constant. + * + * The operation is equivalent to adding [this] copies of unit polynomial to [other]. + */ + public operator fun Int.plus(other: P): P = optimizedAddMultiplied(other, one, this) + /** + * Returns difference between the integer represented as polynomial and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit polynomial from [other]. + */ + public operator fun Int.minus(other: P): P = optimizedAddMultiplied(-other, one, this) + /** + * Returns product of the integer represented as polynomial and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + public operator fun Int.times(other: P): P = optimizedMultiply(other, this) + // endregion + + // region Constant-constant relation + /** + * Returns the same constant. + */ + @JvmName("constantUnaryPlus") + @JsName("constantUnaryPlus") + public operator fun C.unaryPlus(): C = this + /** + * Returns negation of the constant. + */ + @JvmName("constantUnaryMinus") + @JsName("constantUnaryMinus") + public operator fun C.unaryMinus(): C + /** + * Returns sum of the constants. + */ + @JvmName("constantPlus") + @JsName("constantPlus") + public operator fun C.plus(other: C): C + /** + * Returns difference of the constants. + */ + @JvmName("constantMinus") + @JsName("constantMinus") + public operator fun C.minus(other: C): C + /** + * Returns product of the constants. + */ + @JvmName("constantTimes") + @JsName("constantTimes") + public operator fun C.times(other: C): C + + /** + * Check if the instant is zero constant. + */ + @JvmName("constantIsZero") + public fun C.isZero(): Boolean + /** + * Check if the instant is NOT zero constant. + */ + @JvmName("constantIsNotZero") + public fun C.isNotZero(): Boolean + /** + * Check if the instant is unit constant. + */ + @JvmName("constantIsOne") + public fun C.isOne(): Boolean + /** + * Check if the instant is NOT unit constant. + */ + @JvmName("constantIsNotOne") + public fun C.isNotOne(): Boolean + /** + * Check if the instant is minus unit constant. + */ + @JvmName("constantIsMinusOne") + public fun C.isMinusOne(): Boolean + /** + * Check if the instant is NOT minus unit constant. + */ + @JvmName("constantIsNotMinusOne") + public fun C.isNotMinusOne(): Boolean + // endregion + + // region Constant-polynomial relation + /** + * Returns sum of the constant represented as polynomial and the polynomial. + */ + public operator fun C.plus(other: P): P + /** + * Returns difference between the constant represented as polynomial and the polynomial. + */ + public operator fun C.minus(other: P): P + /** + * Returns product of the constant represented as polynomial and the polynomial. + */ + public operator fun C.times(other: P): P + // endregion + + // region Polynomial-constant relation + /** + * Returns sum of the constant represented as polynomial and the polynomial. + */ + public operator fun P.plus(other: C): P + /** + * Returns difference between the constant represented as polynomial and the polynomial. + */ + public operator fun P.minus(other: C): P + /** + * Returns product of the constant represented as polynomial and the polynomial. + */ + public operator fun P.times(other: C): P + // endregion + + // region Polynomial-polynomial relation + /** + * 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 + + /** + * Check if the instant is zero polynomial. + */ + public fun P.isZero(): Boolean = this == zero + /** + * Check if the instant is NOT zero polynomial. + */ + public fun P.isNotZero(): Boolean = this != zero + /** + * Check if the instant is unit polynomial. + */ + public fun P.isOne(): Boolean = this == one + /** + * Check if the instant is NOT unit polynomial. + */ + public fun P.isNotOne(): Boolean = this != one + /** + * Check if the instant is minus unit polynomial. + */ + public fun P.isMinusOne(): Boolean = this == -one + /** + * Check if the instant is NOT minus unit polynomial. + */ + public fun P.isNotMinusOne(): Boolean = this != -one + + /** + * Instance of zero polynomial (zero of the polynomial ring). + */ + override val zero: P + /** + * Instance of unit polynomial (unit of the polynomial ring). + */ + override val one: P + + /** + * Checks equality of the polynomials. + */ + @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") + public fun P.equals(other: P): Boolean + // endregion + + // Not sure is it necessary... + // region Polynomial properties + /** + * 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 + + /** + * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. + */ + public fun P.isConstant(): Boolean = degree <= 0 + /** + * Checks if the instant is **not** constant polynomial (of degree no more than 0) over considered ring. + */ + public fun P.isNotConstant(): Boolean = !isConstant() + /** + * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. + */ + public fun P.isNonZeroConstant(): Boolean = degree == 0 + /** + * Checks if the instant is **not** constant non-zero polynomial (of degree no more than 0) over considered ring. + */ + public fun P.isNotNonZeroConstant(): Boolean = !isNonZeroConstant() + /** + * If polynomial is a constant polynomial represents and returns it as constant. + * Otherwise, (when the polynomial is not constant polynomial) returns `null`. + */ + public fun P.asConstantOrNull(): C? + /** + * If polynomial is a constant polynomial represents and returns it as constant. + * Otherwise, (when the polynomial is not constant polynomial) raises corresponding exception. + */ + public fun P.asConstant(): C = asConstantOrNull() ?: error("Can not represent non-constant polynomial as a constant") + // endregion + + // region Legacy of Ring interface + override fun add(left: P, right: P): P = left + right + override fun multiply(left: P, right: P): P = left * right + // endregion + + public companion object { + // TODO: All of this should be moved to algebraic structures' place for utilities + // TODO: Move receiver to context receiver + /** + * Multiplication of element and integer. + * + * @receiver the multiplicand. + * @param other the multiplier. + * @return the difference. + */ + internal tailrec fun Group.optimizedMultiply(arg: C, other: Int): C = + when { + other == 0 -> zero + other == 1 -> arg + other == -1 -> -arg + other % 2 == 0 -> optimizedMultiply(arg + arg, other / 2) + other % 2 == 1 -> optimizedAddMultiplied(arg, arg + arg, other / 2) + other % 2 == -1 -> optimizedAddMultiplied(-arg, arg + arg, other / 2) + else -> error("Error in multiplication group instant by integer: got reminder by division by 2 different from 0, 1 and -1") + } + + // TODO: Move receiver to context receiver + /** + * Adds product of [arg] and [multiplier] to [base]. + * + * @receiver the algebra to provide multiplication. + * @param base the augend. + * @param arg the multiplicand. + * @param multiplier the multiplier. + * @return sum of the augend [base] and product of the multiplicand [arg] and the multiplier [multiplier]. + * @author Gleb Minaev + */ + internal tailrec fun Group.optimizedAddMultiplied(base: C, arg: C, multiplier: Int): C = + when { + multiplier == 0 -> base + multiplier == 1 -> base + arg + multiplier == -1 -> base - arg + multiplier % 2 == 0 -> optimizedAddMultiplied(base, arg + arg, multiplier / 2) + multiplier % 2 == 1 -> optimizedAddMultiplied(base + arg, arg + arg, multiplier / 2) + multiplier % 2 == -1 -> optimizedAddMultiplied(base + arg, arg + arg, multiplier / 2) + else -> error("Error in multiplication group instant by integer: got reminder by division by 2 different from 0, 1 and -1") + } + } +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt index 16af7f555..cfd21d552 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt @@ -117,16 +117,16 @@ public fun > PiecewisePolynomial( * Return a value of polynomial function with given [ring] a given [arg] or null if argument is outside piecewise * definition. */ -public fun , C : Ring> PiecewisePolynomial.value(ring: C, arg: T): T? = - findPiece(arg)?.value(ring, arg) +public fun , C : Ring> PiecewisePolynomial.substitute(ring: C, arg: T): T? = + findPiece(arg)?.substitute(ring, arg) /** * Convert this polynomial to a function returning nullable value (null if argument is outside piecewise range). */ -public fun , C : Ring> PiecewisePolynomial.asFunction(ring: C): (T) -> T? = { value(ring, it) } +public fun , C : Ring> PiecewisePolynomial.asFunction(ring: C): (T) -> T? = { substitute(ring, it) } /** * Convert this polynomial to a function using [defaultValue] for arguments outside the piecewise range. */ public fun , C : Ring> PiecewisePolynomial.asFunction(ring: C, defaultValue: T): (T) -> T = - { value(ring, it) ?: defaultValue } + { substitute(ring, it) ?: defaultValue } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index a36d36f52..30280a396 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -5,128 +5,371 @@ package space.kscience.kmath.functions -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.functions.AbstractPolynomialSpace.Companion.optimizedAddMultiplied +import space.kscience.kmath.functions.AbstractPolynomialSpace.Companion.optimizedMultiply import space.kscience.kmath.operations.* -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract +import kotlin.jvm.JvmName import kotlin.math.max -import kotlin.math.pow +import kotlin.math.min /** * Polynomial coefficients model without fixation on specific context they are applied to. * * @param coefficients constant is the leftmost coefficient. */ -public class Polynomial(public val coefficients: List) { +public class Polynomial(public val coefficients: List) : AbstractPolynomial { override fun toString(): String = "Polynomial$coefficients" + +// public companion object { +// /** +// * Default name of variables used in string representations. +// * +// * @see Polynomial.toString +// */ +// public var defaultVariableName: String = "x" +// +// /** +// * Represents result of division with remainder. +// */ +// public data class DividingResult( +// val quotient: Polynomial, +// val reminder: Polynomial +// ) +// } } /** - * Returns a [Polynomial] instance with given [coefficients]. + * Represents internal [Polynomial] errors. + */ +internal class PolynomialError(message: String): Error(message) + +// region Constructors and converters + +/** + * Returns a [Polynomial] instance with given [coefficients]. The collection of coefficients will be reversed if + * [reverse] parameter is true. */ @Suppress("FunctionName") -public fun Polynomial(vararg coefficients: T): Polynomial = Polynomial(coefficients.toList()) +public fun Polynomial(coefficients: List, reverse: Boolean = false): Polynomial = + Polynomial(with(coefficients) { if (reverse) reversed() else this }) /** - * Evaluates the value of the given double polynomial for given double argument. + * Returns a [Polynomial] instance with given [coefficients]. The collection of coefficients will be reversed if + * [reverse] parameter is true. */ -public fun Polynomial.value(arg: Double): Double = coefficients.reduceIndexed { index, acc, c -> - acc + c * arg.pow(index) -} +@Suppress("FunctionName") +public fun Polynomial(vararg coefficients: T, reverse: Boolean = false): Polynomial = + Polynomial(with(coefficients) { if (reverse) reversed() else toList() }) + +public fun T.asPolynomial() : Polynomial = Polynomial(listOf(this)) + +// endregion /** - * Evaluates the value of the given polynomial for given argument. - * https://en.wikipedia.org/wiki/Horner%27s_method - */ -public fun > Polynomial.value(ring: C, arg: T): T = ring { - if (coefficients.isEmpty()) return@ring zero - var result: T = coefficients.last() - for (j in coefficients.size - 2 downTo 0) { - result = (arg * result) + coefficients[j] - } - return result -} - -/** - * Represent the polynomial as a regular context-less function. - */ -public fun > Polynomial.asFunction(ring: C): (T) -> T = { value(ring, it) } - -/** - * Create a polynomial witch represents differentiated version of this polynomial - */ -@UnstableKMathAPI -public fun Polynomial.differentiate( - algebra: A, -): Polynomial where A : Ring, A : NumericAlgebra = algebra { - Polynomial(coefficients.drop(1).mapIndexed { index, t -> number(index) * t }) -} - -/** - * Create a polynomial witch represents indefinite integral version of this polynomial - */ -@UnstableKMathAPI -public fun Polynomial.integrate( - algebra: A, -): Polynomial where A : Field, A : NumericAlgebra = algebra { - val integratedCoefficients = buildList(coefficients.size + 1) { - add(zero) - coefficients.forEachIndexed{ index, t -> add(t / (number(index) + one)) } - } - Polynomial(integratedCoefficients) -} - -/** - * Compute a definite integral of a given polynomial in a [range] - */ -@UnstableKMathAPI -public fun > Polynomial.integrate( - algebra: Field, - range: ClosedRange, -): T = algebra { - val integral = integrate(algebra) - integral.value(algebra, range.endInclusive) - integral.value(algebra, range.start) -} - -/** - * Space of polynomials. + * Space of polynomials constructed over ring. * - * @param T the type of operated polynomials. - * @param C the intersection of [Ring] of [T] and [ScaleOperations] of [T]. - * @param ring the [C] instance. + * @param C the type of constants. Polynomials have them 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 PolynomialSpace( - private val ring: C, -) : Group>, ScaleOperations> where C : Ring, C : ScaleOperations { - override val zero: Polynomial = Polynomial(emptyList()) +@Suppress("INAPPLICABLE_JVM_NAME") // KT-31420 +public open class PolynomialSpace>( + public val ring: A, +) : AbstractPolynomialSpace>{ + // region Constant-integer relation + @JvmName("constantIntPlus") + public override operator fun C.plus(other: Int): C = ring { optimizedAddMultiplied(this@plus, one, other) } + @JvmName("constantIntMinus") + public override operator fun C.minus(other: Int): C = ring { optimizedAddMultiplied(this@minus, one, -other) } + @JvmName("constantIntTimes") + public override operator fun C.times(other: Int): C = ring { optimizedMultiply(this@times, other) } + // endregion - override fun Polynomial.unaryMinus(): Polynomial = ring { + // region Integer-constant relation + @JvmName("intConstantPlus") + public override operator fun Int.plus(other: C): C = ring { optimizedAddMultiplied(other, one, this@plus) } + @JvmName("intConstantMinus") + public override operator fun Int.minus(other: C): C = ring { optimizedAddMultiplied(-other, one, this@minus) } + @JvmName("intConstantTimes") + public override operator fun Int.times(other: C): C = ring { optimizedMultiply(other, this@times) } + // endregion + + // region Polynomial-integer relation + public override operator fun Polynomial.plus(other: Int): Polynomial = + if (other == 0) this + else + Polynomial( + coefficients + .toMutableList() + .apply { + if (isEmpty()) this[0] = ring.zero + other + else this[0] = this[0]!! + other + } + ) + public override operator fun Polynomial.minus(other: Int): Polynomial = + if (other == 0) this + else + Polynomial( + coefficients + .toMutableList() + .apply { + if (isEmpty()) this[0] = ring.zero - other + else this[0] = this[0]!! - other + } + ) + public override operator fun Polynomial.times(other: Int): Polynomial = + if (other == 0) zero + else Polynomial( + coefficients + .subList(0, degree + 1) + .map { it * other } + ) + // endregion + + // region Integer-polynomial relation + public override operator fun Int.plus(other: Polynomial): Polynomial = + if (this == 0) other + else + Polynomial( + other.coefficients + .toMutableList() + .apply { + if (isEmpty()) this[0] = ring.zero + this@plus + else this[0] = this[0]!! + this@plus + } + ) + public override operator fun Int.minus(other: Polynomial): Polynomial = + if (this == 0) other + else + Polynomial( + other.coefficients + .toMutableList() + .apply { + if (isEmpty()) this[0] = ring.zero - this@minus + else this[0] = this[0]!! - this@minus + } + ) + public override operator fun Int.times(other: Polynomial): Polynomial = + if (this == 0) zero + else Polynomial( + other.coefficients + .subList(0, other.degree + 1) + .map { it * this } + ) + // endregion + + // region Constant-constant relation + @JvmName("constantUnaryMinus") + public override operator fun C.unaryMinus(): C = ring { -this@unaryMinus } + @JvmName("constantPlus") + public override operator fun C.plus(other: C): C = ring { this@plus + other } + @JvmName("constantMinus") + public override operator fun C.minus(other: C): C = ring { this@minus - other } + @JvmName("constantTimes") + public override operator fun C.times(other: C): C = ring { this@times * other } + @JvmName("constantIsZero") + public override fun C.isZero(): Boolean = ring { this == zero } + @JvmName("constantIsNotZero") + public override fun C.isNotZero(): Boolean = ring { this != zero } + @JvmName("constantIsOne") + public override fun C.isOne(): Boolean = ring { this == one } + @JvmName("constantIsNotOne") + public override fun C.isNotOne(): Boolean = ring { this != one } + @JvmName("constantIsMinusOne") + public override fun C.isMinusOne(): Boolean = ring { this == -one } + @JvmName("constantIsNotMinusOne") + public override fun C.isNotMinusOne(): Boolean = ring { this != -one } + // endregion + + // region Constant-polynomial relation + public override operator fun C.plus(other: Polynomial): Polynomial = + with(other.coefficients) { + if (isEmpty()) Polynomial(listOf(this@plus)) + else Polynomial( + toMutableList() + .apply { + this[0] += this@plus + } + ) + } +// if (degree == -1) UnivariatePolynomial(other) else UnivariatePolynomial( +// listOf(coefficients[0] + other) + coefficients.subList(1, degree + 1) +// ) + public override operator fun C.minus(other: Polynomial): Polynomial = + with(other.coefficients) { + if (isEmpty()) Polynomial(listOf(-this@minus)) + else Polynomial( + toMutableList() + .apply { + this[0] -= this@minus + } + ) + } +// if (degree == -1) UnivariatePolynomial(other) else UnivariatePolynomial( +// listOf(coefficients[0] + other) + coefficients.subList(1, degree + 1) +// ) + public override operator fun C.times(other: Polynomial): Polynomial = + Polynomial( + other.coefficients +// .subList(0, other.degree + 1) + .map { it * this } + ) + // endregion + + // region Polynomial-constant relation + public override operator fun Polynomial.plus(other: C): Polynomial = + if (other.isZero()) this + else with(coefficients) { + if (isEmpty()) Polynomial(listOf(other)) + else Polynomial( + toMutableList() + .apply { + this[0] += other + } + ) + } +// if (degree == -1) UnivariatePolynomial(other) else UnivariatePolynomial( +// listOf(coefficients[0] + other) + coefficients.subList(1, degree + 1) +// ) + public override operator fun Polynomial.minus(other: C): Polynomial = + with(coefficients) { + if (isEmpty()) Polynomial(listOf(other)) + else Polynomial( + toMutableList() + .apply { + this[0] -= other + } + ) + } +// if (degree == -1) UnivariatePolynomial(-other) else UnivariatePolynomial( +// listOf(coefficients[0] - other) + coefficients.subList(1, degree + 1) +// ) + public override operator fun Polynomial.times(other: C): Polynomial = + Polynomial( + coefficients +// .subList(0, degree + 1) + .map { it * other } + ) + // endregion + + // region Polynomial-polynomial relation + public override operator fun Polynomial.unaryMinus(): Polynomial = Polynomial(coefficients.map { -it }) - } - - override fun add(left: Polynomial, right: Polynomial): Polynomial { - val dim = max(left.coefficients.size, right.coefficients.size) - - return ring { - Polynomial(List(dim) { index -> - left.coefficients.getOrElse(index) { zero } + right.coefficients.getOrElse(index) { zero } - }) + public override operator fun Polynomial.plus(other: Polynomial): Polynomial = + Polynomial( + (0..max(degree, other.degree)) + .map { + when { + it > degree -> other.coefficients[it] + it > other.degree -> coefficients[it] + else -> coefficients[it] + other.coefficients[it] + } + } + .ifEmpty { listOf(ring.zero) } + ) + public override operator fun Polynomial.minus(other: Polynomial): Polynomial = + Polynomial( + (0..max(degree, other.degree)) + .map { + when { + it > degree -> -other.coefficients[it] + it > other.degree -> coefficients[it] + else -> coefficients[it] - other.coefficients[it] + } + } + .ifEmpty { listOf(ring.zero) } + ) + public override operator fun Polynomial.times(other: Polynomial): Polynomial { + val thisDegree = degree + val otherDegree = other.degree + return when { + thisDegree == -1 -> this + otherDegree == -1 -> other + else -> + Polynomial( + (0..(thisDegree + otherDegree)) + .map { d -> + (max(0, d - otherDegree)..(min(thisDegree, d))) + .map { coefficients[it] * other.coefficients[d - it] } + .reduce { acc, rational -> acc + rational } + } + ) } } - override fun scale(a: Polynomial, value: Double): Polynomial = - ring { Polynomial(List(a.coefficients.size) { index -> a.coefficients[index] * value }) } + public override fun Polynomial.isZero(): Boolean = coefficients.all { it.isZero() } + public override fun Polynomial.isNotZero(): Boolean = coefficients.any { it.isNotZero() } + public override fun Polynomial.isOne(): Boolean = + with(coefficients) { isNotEmpty() && asSequence().withIndex().any { (index, c) -> if (index == 0) c.isOne() else c.isZero() } } // TODO: It's better to write new methods like `anyIndexed`. But what's better way to do it? + public override fun Polynomial.isNotOne(): Boolean = !isOne() + public override fun Polynomial.isMinusOne(): Boolean = + with(coefficients) { isNotEmpty() && asSequence().withIndex().any { (index, c) -> if (index == 0) c.isMinusOne() else c.isZero() } } // TODO: It's better to write new methods like `anyIndexed`. But what's better way to do it? + public override fun Polynomial.isNotMinusOne(): Boolean = !isMinusOne() + + override val zero: Polynomial = Polynomial(emptyList()) + override val one: Polynomial = Polynomial(listOf(ring.one)) + + @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") + public override fun Polynomial.equals(other: Polynomial): Boolean = + when { + this === other -> true + else -> { + if (this.degree == other.degree) + (0..degree).all { coefficients[it] == other.coefficients[it] } + else false + } + } + // endregion + + // Not sure is it necessary... + // region Polynomial properties + public override val Polynomial.degree: Int get() = coefficients.indexOfLast { it != ring.zero } + + public override fun Polynomial.asConstantOrNull(): C? = + with(coefficients) { + when { + isEmpty() -> ring.zero + degree > 0 -> null + else -> first() + } + } + public override fun Polynomial.asConstant(): C = asConstantOrNull() ?: error("Can not represent non-constant polynomial as a constant") + + @Suppress("NOTHING_TO_INLINE") + public inline fun Polynomial.substitute(argument: C): C = this.substitute(ring, argument) + @Suppress("NOTHING_TO_INLINE") + public inline fun Polynomial.substitute(argument: Polynomial): Polynomial = this.substitute(ring, argument) + + @Suppress("NOTHING_TO_INLINE") + public inline fun Polynomial.asFunction(): (C) -> C = { this.substitute(ring, it) } + @Suppress("NOTHING_TO_INLINE") + public inline fun Polynomial.asFunctionOnConstants(): (C) -> C = { this.substitute(ring, it) } + @Suppress("NOTHING_TO_INLINE") + public inline fun Polynomial.asFunctionOnPolynomials(): (Polynomial) -> Polynomial = { this.substitute(ring, it) } /** * Evaluates the polynomial for the given value [arg]. */ - public operator fun Polynomial.invoke(arg: T): T = value(ring, arg) - - public fun Polynomial.asFunction(): (T) -> T = asFunction(ring) + @Suppress("NOTHING_TO_INLINE") + public inline operator fun Polynomial.invoke(argument: C): C = this.substitute(ring, argument) + @Suppress("NOTHING_TO_INLINE") + public inline operator fun Polynomial.invoke(argument: Polynomial): Polynomial = this.substitute(ring, argument) + // endregion } -public inline fun C.polynomial(block: PolynomialSpace.() -> R): R where C : Ring, C : ScaleOperations { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return PolynomialSpace(this).block() +/** + * 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 ScalablePolynomialSpace( + ring: A, +) : PolynomialSpace(ring), ScaleOperations> where A : Ring, A : ScaleOperations { + + override fun scale(a: Polynomial, value: Double): Polynomial = + ring { Polynomial(List(a.coefficients.size) { index -> a.coefficients[index] * value }) } + } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt new file mode 100644 index 000000000..1a3eb7874 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt @@ -0,0 +1,139 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.* +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract +import kotlin.jvm.JvmName +import kotlin.math.pow + + +// region Utilities + +/** + * Removes zeros on the end of the coefficient list of polynomial. + */ +//context(PolynomialSpace) +//fun > Polynomial.removeZeros() : Polynomial = +// if (degree > -1) Polynomial(coefficients.subList(0, degree + 1)) else zero + +/** + * Crates a [PolynomialSpace] over received ring. + */ +public fun > A.polynomial(): PolynomialSpace = + PolynomialSpace(this) + +/** + * Crates a [PolynomialSpace]'s scope over received ring. + */ +public inline fun , R> A.polynomial(block: PolynomialSpace.() -> R): R { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return PolynomialSpace(this).block() +} + +/** + * Crates a [ScalablePolynomialSpace] over received scalable ring. + */ +public fun A.scalablePolynomial(): ScalablePolynomialSpace where A : Ring, A : ScaleOperations = + ScalablePolynomialSpace(this) + +/** + * Crates a [ScalablePolynomialSpace]'s scope over received scalable ring. + */ +public inline fun A.scalablePolynomial(block: ScalablePolynomialSpace.() -> R): R where A : Ring, A : ScaleOperations { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return ScalablePolynomialSpace(this).block() +} + +// endregion + +// region Polynomial substitution and functional representation + +// TODO: May be apply Horner's method too? +/** + * Evaluates the value of the given double polynomial for given double argument. + */ +public fun Polynomial.substitute(arg: Double): Double = + coefficients.reduceIndexedOrNull { index, acc, c -> + acc + c * arg.pow(index) + } ?: .0 + +/** + * Evaluates the value of the given polynomial for given argument. + * + * It is an implementation of [Horner's method](https://en.wikipedia.org/wiki/Horner%27s_method). + */ +public fun Polynomial.substitute(ring: Ring, arg: C): C = ring { + if (coefficients.isEmpty()) return@ring zero + var result: C = coefficients.last() + for (j in coefficients.size - 2 downTo 0) { + result = (arg * result) + coefficients[j] + } + return result +} + +// TODO: (Waiting for hero) Replace with optimisation: the [result] may be unboxed, and all operations may be performed +// as soon as possible on it +public fun Polynomial.substitute(ring: Ring, arg: Polynomial) : Polynomial = ring.polynomial { + if (coefficients.isEmpty()) return zero + var result: Polynomial = coefficients.last().asPolynomial() + for (j in coefficients.size - 2 downTo 0) { + result = (arg * result) + coefficients[j] + } + return result +} + +/** + * Represent the polynomial as a regular context-less function. + */ +public fun > Polynomial.asFunction(ring: A): (C) -> C = { substitute(ring, it) } + +/** + * Represent the polynomial as a regular context-less function. + */ +public fun > Polynomial.asPolynomialFunctionOver(ring: A): (Polynomial) -> Polynomial = { substitute(ring, it) } + +// endregion + +// region Algebraic derivative and antiderivative + +/** + * Returns algebraic derivative of received polynomial. + */ +@UnstableKMathAPI +public fun Polynomial.derivative( + algebra: A, +): Polynomial where A : Ring, A : NumericAlgebra = algebra { + Polynomial(coefficients.drop(1).mapIndexed { index, t -> number(index) * t }) +} + +/** + * Create a polynomial witch represents indefinite integral version of this polynomial + */ +@UnstableKMathAPI +public fun Polynomial.antiderivative( + algebra: A, +): Polynomial where A : Field, A : NumericAlgebra = algebra { + val integratedCoefficients = buildList(coefficients.size + 1) { + add(zero) + coefficients.forEachIndexed{ index, t -> add(t / (number(index) + one)) } + } + Polynomial(integratedCoefficients) +} + +/** + * Compute a definite integral of a given polynomial in a [range] + */ +@UnstableKMathAPI +public fun > Polynomial.integrate( + algebra: Field, + range: ClosedRange, +): C = algebra { + val integral = antiderivative(algebra) + integral.substitute(algebra, range.endInclusive) - integral.substitute(algebra, range.start) +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt index eb88d9ae0..0fcd4c6e5 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 @@ -7,6 +7,7 @@ package space.kscience.kmath.integration import space.kscience.kmath.functions.PiecewisePolynomial import space.kscience.kmath.functions.integrate +import space.kscience.kmath.functions.antiderivative import space.kscience.kmath.interpolation.PolynomialInterpolator import space.kscience.kmath.interpolation.SplineInterpolator import space.kscience.kmath.interpolation.interpolatePolynomials @@ -23,7 +24,7 @@ import space.kscience.kmath.structures.MutableBufferFactory @OptIn(PerformancePitfall::class) @UnstableKMathAPI public fun > PiecewisePolynomial.integrate(algebra: Field): PiecewisePolynomial = - PiecewisePolynomial(pieces.map { it.first to it.second.integrate(algebra) }) + PiecewisePolynomial(pieces.map { it.first to it.second.antiderivative(algebra) }) /** * Compute definite integral of given [PiecewisePolynomial] piece by piece in a given [range] diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt index 2266092a3..62819be0c 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt @@ -10,7 +10,7 @@ package space.kscience.kmath.interpolation import space.kscience.kmath.data.XYColumnarData import space.kscience.kmath.functions.PiecewisePolynomial import space.kscience.kmath.functions.asFunction -import space.kscience.kmath.functions.value +import space.kscience.kmath.functions.substitute import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Ring import space.kscience.kmath.structures.Buffer @@ -34,7 +34,7 @@ public interface PolynomialInterpolator> : Interpolator): PiecewisePolynomial override fun interpolate(points: XYColumnarData): (T) -> T = { x -> - interpolatePolynomials(points).value(algebra, x) ?: getDefaultValue() + interpolatePolynomials(points).substitute(algebra, x) ?: getDefaultValue() } } diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt index 05c16d17e..e0f0e32a4 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt @@ -5,13 +5,22 @@ package space.kscience.kmath.functions +import space.kscience.kmath.operations.algebra import kotlin.test.Test import kotlin.test.assertEquals class PolynomialTest { + @Test + fun simple_polynomial_test() { + Double.algebra.scalablePolynomial { + val x = Polynomial(listOf(0.0, 1.0)) + val polynomial = x * x - 2 * x + 1 + assertEquals(0.0, polynomial.substitute(1.0), 0.001) + } + } @Test fun testIntegration() { val polynomial = Polynomial(1.0, -2.0, 1.0) - assertEquals(0.0, polynomial.value(1.0), 0.001) + assertEquals(0.0, polynomial.substitute(1.0), 0.001) } } \ No newline at end of file -- 2.34.1 From cab59581071d25e2a569ad3bb13eb799e42e046f Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Thu, 10 Mar 2022 01:44:14 +0300 Subject: [PATCH 014/275] Added abstract rational functions --- .../kmath/functions/AbstractPolynomial.kt | 16 +- .../functions/AbstractRationalFunction.kt | 507 ++++++++++++++++++ 2 files changed, 515 insertions(+), 8 deletions(-) create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt index f6a617656..237a72bcc 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt @@ -70,19 +70,19 @@ public interface AbstractPolynomialSpace> : Ring

// region Polynomial-integer relation /** - * Returns sum of the constant and the integer represented as polynomial. + * Returns sum of the polynomial and the integer represented as polynomial. * * The operation is equivalent to adding [other] copies of unit polynomial to [this]. */ public operator fun P.plus(other: Int): P = optimizedAddMultiplied(this, one, other) /** - * Returns difference between the constant and the integer represented as polynomial. + * Returns difference between the polynomial and the integer represented as polynomial. * * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. */ public operator fun P.minus(other: Int): P = optimizedAddMultiplied(this, one, -other) /** - * Returns product of the constant and the integer represented as polynomial. + * Returns product of the polynomial and the integer represented as polynomial. * * The operation is equivalent to sum of [other] copies of [this]. */ @@ -91,19 +91,19 @@ public interface AbstractPolynomialSpace> : Ring

// region Integer-polynomial relation /** - * Returns sum of the integer represented as polynomial and the constant. + * Returns sum of the integer represented as 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 = optimizedAddMultiplied(other, one, this) /** - * Returns difference between the integer represented as polynomial and the constant. + * Returns difference between the integer represented as 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 = optimizedAddMultiplied(-other, one, this) /** - * Returns product of the integer represented as polynomial and the constant. + * Returns product of the integer represented as polynomial and the polynomial. * * The operation is equivalent to sum of [this] copies of [other]. */ @@ -254,11 +254,11 @@ public interface AbstractPolynomialSpace> : Ring

/** * Instance of zero polynomial (zero of the polynomial ring). */ - override val zero: P + public override val zero: P /** * Instance of unit polynomial (unit of the polynomial ring). */ - override val one: P + public override val one: P /** * Checks equality of the polynomials. diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt new file mode 100644 index 000000000..5cb570c9f --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt @@ -0,0 +1,507 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.functions.AbstractPolynomialSpace.Companion.optimizedAddMultiplied +import space.kscience.kmath.functions.AbstractPolynomialSpace.Companion.optimizedMultiply +import space.kscience.kmath.operations.* +import kotlin.js.JsName +import kotlin.jvm.JvmName + + +/** + * Abstraction of rational function. + */ +public interface AbstractRationalFunction> + +@Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") +public interface AbstractRationalFunctionalSpace, R: AbstractRationalFunction> : Ring { + // region Constant-integer relation + /** + * Returns sum of the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. + */ + @JvmName("constantIntPlus") + public operator fun C.plus(other: Int): C + /** + * Returns difference between the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. + */ + @JvmName("constantIntMinus") + public operator fun C.minus(other: Int): C + /** + * Returns product of the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + @JvmName("constantIntTimes") + public operator fun C.times(other: Int): C + // endregion + + // region Integer-constant relation + /** + * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. + */ + @JvmName("intConstantPlus") + public operator fun Int.plus(other: C): C + /** + * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. + */ + @JvmName("intConstantMinus") + public operator fun Int.minus(other: C): C + /** + * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + @JvmName("intConstantTimes") + public operator fun Int.times(other: C): C + // endregion + + // region Polynomial-integer relation + /** + * Returns sum of the constant and the integer represented as polynomial. + * + * The operation is equivalent to adding [other] copies of unit polynomial to [this]. + */ + public operator fun P.plus(other: Int): P + /** + * Returns difference between the constant and the integer represented as polynomial. + * + * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. + */ + public operator fun P.minus(other: Int): P + /** + * Returns product of the constant and the integer represented as polynomial. + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + public operator fun P.times(other: Int): P + // endregion + + // region Integer-polynomial relation + /** + * Returns sum of the integer represented as polynomial and the constant. + * + * The operation is equivalent to adding [this] copies of unit polynomial to [other]. + */ + public operator fun Int.plus(other: P): P + /** + * Returns difference between the integer represented as polynomial and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit polynomial from [other]. + */ + public operator fun Int.minus(other: P): P + /** + * Returns product of the integer represented as polynomial and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + public operator fun Int.times(other: P): P + // endregion + + // region Rational-integer relation + /** + * Returns sum of the rational function and the integer represented as rational function. + * + * The operation is equivalent to adding [other] copies of unit polynomial to [this]. + */ + public operator fun R.plus(other: Int): R = optimizedAddMultiplied(this, one, other) + /** + * Returns difference between the rational function and the integer represented as rational function. + * + * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. + */ + public operator fun R.minus(other: Int): R = optimizedAddMultiplied(this, one, -other) + /** + * Returns product of the rational function and the integer represented as rational function. + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + public operator fun R.times(other: Int): R = optimizedMultiply(this, other) + // endregion + + // region Integer-Rational relation + /** + * Returns sum of the integer represented as 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 = optimizedAddMultiplied(other, one, this) + /** + * Returns difference between the integer represented as 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 = optimizedAddMultiplied(-other, one, this) + /** + * Returns product of the integer represented as 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 = optimizedMultiply(other, this) + // endregion + + // region Constant-constant relation + /** + * Returns the same constant. + */ + @JvmName("constantUnaryPlus") + @JsName("constantUnaryPlus") + public operator fun C.unaryPlus(): C = this + /** + * Returns negation of the constant. + */ + @JvmName("constantUnaryMinus") + @JsName("constantUnaryMinus") + public operator fun C.unaryMinus(): C + /** + * Returns sum of the constants. + */ + @JvmName("constantPlus") + @JsName("constantPlus") + public operator fun C.plus(other: C): C + /** + * Returns difference of the constants. + */ + @JvmName("constantMinus") + @JsName("constantMinus") + public operator fun C.minus(other: C): C + /** + * Returns product of the constants. + */ + @JvmName("constantTimes") + @JsName("constantTimes") + public operator fun C.times(other: C): C + + /** + * Check if the instant is zero constant. + */ + @JvmName("constantIsZero") + public fun C.isZero(): Boolean + /** + * Check if the instant is NOT zero constant. + */ + @JvmName("constantIsNotZero") + public fun C.isNotZero(): Boolean + /** + * Check if the instant is unit constant. + */ + @JvmName("constantIsOne") + public fun C.isOne(): Boolean + /** + * Check if the instant is NOT unit constant. + */ + @JvmName("constantIsNotOne") + public fun C.isNotOne(): Boolean + /** + * Check if the instant is minus unit constant. + */ + @JvmName("constantIsMinusOne") + public fun C.isMinusOne(): Boolean + /** + * Check if the instant is NOT minus unit constant. + */ + @JvmName("constantIsNotMinusOne") + public fun C.isNotMinusOne(): Boolean + // endregion + + // region Constant-polynomial relation + /** + * Returns sum of the constant represented as polynomial and the polynomial. + */ + public operator fun C.plus(other: P): P + /** + * Returns difference between the constant represented as polynomial and the polynomial. + */ + public operator fun C.minus(other: P): P + /** + * Returns product of the constant represented as polynomial and the polynomial. + */ + public operator fun C.times(other: P): P + // endregion + + // region Polynomial-constant relation + /** + * Returns sum of the constant represented as polynomial and the polynomial. + */ + public operator fun P.plus(other: C): P + /** + * Returns difference between the constant represented as polynomial and the polynomial. + */ + public operator fun P.minus(other: C): P + /** + * Returns product of the constant represented as polynomial and the polynomial. + */ + public operator fun P.times(other: C): P + // endregion + + // region Polynomial-polynomial relation + /** + * Returns the same polynomial. + */ + public operator fun P.unaryPlus(): P = this + /** + * Returns negation of the polynomial. + */ + public operator fun P.unaryMinus(): P + /** + * Returns sum of the polynomials. + */ + public operator fun P.plus(other: P): P + /** + * Returns difference of the polynomials. + */ + public operator fun P.minus(other: P): P + /** + * Returns product of the polynomials. + */ + public operator fun P.times(other: P): P + + /** + * Check if the instant is zero polynomial. + */ + public fun P.isZero(): Boolean = this == zeroPolynomial + /** + * Check if the instant is NOT zero polynomial. + */ + public fun P.isNotZero(): Boolean = this != zeroPolynomial + /** + * Check if the instant is unit polynomial. + */ + public fun P.isOne(): Boolean = this == onePolynomial + /** + * Check if the instant is NOT unit polynomial. + */ + public fun P.isNotOne(): Boolean = this != onePolynomial + /** + * Check if the instant is minus unit polynomial. + */ + public fun P.isMinusOne(): Boolean = this == -onePolynomial + /** + * Check if the instant is NOT minus unit polynomial. + */ + public fun P.isNotMinusOne(): Boolean = this != -onePolynomial + + /** + * Instance of zero polynomial (zero of the polynomial ring). + */ + public val zeroPolynomial: P + /** + * Instance of unit polynomial (unit of the polynomial ring). + */ + public val onePolynomial: P + + /** + * Checks equality of the polynomials. + */ + @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") + public fun P.equals(other: P): Boolean + // endregion + + // region Constant-rational relation + /** + * Returns sum of the constant represented as rational function and the rational function. + */ + public operator fun C.plus(other: R): R + /** + * Returns difference between the constant represented as polynomial and the rational function. + */ + public operator fun C.minus(other: R): R + /** + * Returns product of the constant represented as polynomial and the rational function. + */ + public operator fun C.times(other: R): R + // endregion + + // region Rational-constant relation + /** + * Returns sum of the constant represented as rational function and the rational function. + */ + public operator fun R.plus(other: C): R + /** + * Returns difference between the constant represented as rational function and the rational function. + */ + public operator fun R.minus(other: C): R + /** + * Returns product of the constant represented as rational function and the rational function. + */ + public operator fun R.times(other: C): R + // endregion + + // region Polynomial-rational relation + /** + * Returns sum of the polynomial represented as rational function and the rational function. + */ + public operator fun P.plus(other: R): R + /** + * Returns difference between the polynomial represented as polynomial and the rational function. + */ + public operator fun P.minus(other: R): R + /** + * Returns product of the polynomial represented as polynomial and the rational function. + */ + public operator fun P.times(other: R): R + // endregion + + // region Rational-polynomial relation + /** + * Returns sum of the polynomial represented as rational function and the rational function. + */ + public operator fun R.plus(other: P): R + /** + * Returns difference between the polynomial represented as rational function and the rational function. + */ + public operator fun R.minus(other: P): R + /** + * Returns product of the polynomial represented as rational function and the rational function. + */ + public operator fun R.times(other: P): R + // endregion + + // region Rational-rational relation + /** + * 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 + + /** + * Check if the instant is zero rational function. + */ + public fun R.isZero(): Boolean = this == zero + /** + * Check if the instant is NOT zero rational function. + */ + public fun R.isNotZero(): Boolean = this != zero + /** + * Check if the instant is unit rational function. + */ + public fun R.isOne(): Boolean = this == one + /** + * Check if the instant is NOT unit rational function. + */ + public fun R.isNotOne(): Boolean = this != one + /** + * Check if the instant is minus unit rational function. + */ + public fun R.isMinusOne(): Boolean = this == -one + /** + * Check if the instant is NOT minus unit rational function. + */ + public fun R.isNotMinusOne(): Boolean = this != -one + + /** + * 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 + + /** + * Checks equality of the rational functions. + */ + @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") + public fun R.equals(other: R): Boolean + // endregion + + // Not sure is it necessary... + // region Polynomial properties + /** + * 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 + + /** + * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. + */ + public fun P.isConstant(): Boolean = degree <= 0 + /** + * Checks if the instant is **not** constant polynomial (of degree no more than 0) over considered ring. + */ + public fun P.isNotConstant(): Boolean = !isConstant() + /** + * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. + */ + public fun P.isNonZeroConstant(): Boolean = degree == 0 + /** + * Checks if the instant is **not** constant non-zero polynomial (of degree no more than 0) over considered ring. + */ + public fun P.isNotNonZeroConstant(): Boolean = !isNonZeroConstant() + + public fun P.asConstantOrNull(): C? + + public fun P.asConstant(): C = asConstantOrNull() ?: error("Can not represent non-constant polynomial as a constant") + + // endregion + + // Not sure is it necessary... + // region Polynomial properties + /** + * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. + */ + public fun R.isConstant(): Boolean + /** + * Checks if the instant is **not** constant polynomial (of degree no more than 0) over considered ring. + */ + public fun R.isNotConstant(): Boolean = !isConstant() + /** + * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. + */ + public fun R.isNonZeroConstant(): Boolean + /** + * Checks if the instant is **not** constant non-zero polynomial (of degree no more than 0) over considered ring. + */ + public fun R.isNotNonZeroConstant(): Boolean = !isNonZeroConstant() + + public fun R.asConstantOrNull(): C? + + public fun R.asConstant(): C = asConstantOrNull() ?: error("Can not represent non-constant polynomial as a constant") + + // TODO: Перенести в реализацию +// fun R.substitute(argument: C): C +// fun R.substitute(argument: P): R +// fun R.substitute(argument: R): R +// +// fun R.asFunction(): (C) -> C = /*this::substitute*/ { this.substitute(it) } +// fun R.asFunctionOnConstants(): (C) -> C = /*this::substitute*/ { this.substitute(it) } +// fun P.asFunctionOnPolynomials(): (P) -> R = /*this::substitute*/ { this.substitute(it) } +// fun R.asFunctionOnRationalFunctions(): (R) -> R = /*this::substitute*/ { this.substitute(it) } +// +// operator fun R.invoke(argument: C): C = this.substitute(argument) +// operator fun R.invoke(argument: P): R = this.substitute(argument) +// operator fun R.invoke(argument: R): R = this.substitute(argument) + // endregion + + // region Legacy + override fun add(left: R, right: R): R = left + right + override fun multiply(left: R, right: R): R = left * right + // endregion +} \ No newline at end of file -- 2.34.1 From 571c6342ddcead43bbcd99b1583e86366212f802 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sun, 13 Mar 2022 03:25:25 +0300 Subject: [PATCH 015/275] Regenerated READMEs --- README.md | 4 ++-- kmath-ast/README.md | 47 +++++++++++++++++++++++++++++--------- kmath-complex/README.md | 6 ++--- kmath-core/README.md | 6 ++--- kmath-ejml/README.md | 6 ++--- kmath-for-real/README.md | 6 ++--- kmath-functions/README.md | 6 ++--- kmath-jafama/README.md | 6 ++--- kmath-kotlingrad/README.md | 6 ++--- kmath-nd4j/README.md | 6 ++--- kmath-tensors/README.md | 6 ++--- 11 files changed, 65 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 99dd6d00f..76b8ce2f7 100644 --- a/README.md +++ b/README.md @@ -308,8 +308,8 @@ repositories { } dependencies { - api("space.kscience:kmath-core:0.3.0-dev-17") - // api("space.kscience:kmath-core-jvm:0.3.0-dev-17") for jvm-specific version + api("space.kscience:kmath-core:0.3.0-dev-19") + // api("space.kscience:kmath-core-jvm:0.3.0-dev-19") for jvm-specific version } ``` diff --git a/kmath-ast/README.md b/kmath-ast/README.md index bedf17486..9411befe3 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -10,7 +10,7 @@ Extensions to MST API: transformations, dynamic compilation and visualization. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-17`. +The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-19`. **Gradle:** ```gradle @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ast:0.3.0-dev-17' + implementation 'space.kscience:kmath-ast:0.3.0-dev-19' } ``` **Gradle Kotlin DSL:** @@ -31,7 +31,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ast:0.3.0-dev-17") + implementation("space.kscience:kmath-ast:0.3.0-dev-19") } ``` @@ -66,20 +66,19 @@ For example, the following code: ```kotlin import space.kscience.kmath.asm.compileToExpression -import space.kscience.kmath.complex.ComplexField +import space.kscience.kmath.operations.DoubleField -"x+2".parseMath().compileToExpression(ComplexField) +"x^3-x+3".parseMath().compileToExpression(DoubleField) ``` … leads to generation of bytecode, which can be decompiled to the following Java class: ```java -import java.util.Map; -import kotlin.jvm.functions.Function2; -import space.kscience.kmath.asm.internal.MapIntrinsics; -import space.kscience.kmath.complex.Complex; -import space.kscience.kmath.expressions.Expression; -import space.kscience.kmath.expressions.Symbol; +import java.util.*; +import kotlin.jvm.functions.*; +import space.kscience.kmath.asm.internal.*; +import space.kscience.kmath.complex.*; +import space.kscience.kmath.expressions.*; public final class CompiledExpression_45045_0 implements Expression { private final Object[] constants; @@ -91,6 +90,32 @@ public final class CompiledExpression_45045_0 implements Expression { } ``` +For `LongRing`, `IntRing`, and `DoubleField` specialization is supported for better performance: + +```java +import java.util.*; +import space.kscience.kmath.asm.internal.*; +import space.kscience.kmath.expressions.*; + +public final class CompiledExpression_-386104628_0 implements DoubleExpression { + private final SymbolIndexer indexer; + + public SymbolIndexer getIndexer() { + return this.indexer; + } + + public double invoke(double[] arguments) { + double var2 = arguments[0]; + return Math.pow(var2, 3.0D) - var2 + 3.0D; + } + + public final Double invoke(Map arguments) { + double var2 = ((Double)MapIntrinsics.getOrFail(arguments, "x")).doubleValue(); + return Math.pow(var2, 3.0D) - var2 + 3.0D; + } +} +``` + Setting JVM system property `space.kscience.kmath.ast.dump.generated.classes` to `1` makes the translator dump class files to program's working directory, so they can be reviewed manually. #### Limitations diff --git a/kmath-complex/README.md b/kmath-complex/README.md index 92f2435ba..cfaf43aa1 100644 --- a/kmath-complex/README.md +++ b/kmath-complex/README.md @@ -8,7 +8,7 @@ Complex and hypercomplex number systems in KMath. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-17`. +The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-19`. **Gradle:** ```gradle @@ -18,7 +18,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-complex:0.3.0-dev-17' + implementation 'space.kscience:kmath-complex:0.3.0-dev-19' } ``` **Gradle Kotlin DSL:** @@ -29,6 +29,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-complex:0.3.0-dev-17") + implementation("space.kscience:kmath-complex:0.3.0-dev-19") } ``` diff --git a/kmath-core/README.md b/kmath-core/README.md index e765ad50c..4e980baf5 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -15,7 +15,7 @@ performance calculations to code generation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-17`. +The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-19`. **Gradle:** ```gradle @@ -25,7 +25,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-core:0.3.0-dev-17' + implementation 'space.kscience:kmath-core:0.3.0-dev-19' } ``` **Gradle Kotlin DSL:** @@ -36,6 +36,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-core:0.3.0-dev-17") + implementation("space.kscience:kmath-core:0.3.0-dev-19") } ``` diff --git a/kmath-ejml/README.md b/kmath-ejml/README.md index fcd092bf1..24b36aa0d 100644 --- a/kmath-ejml/README.md +++ b/kmath-ejml/README.md @@ -9,7 +9,7 @@ EJML based linear algebra implementation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-17`. +The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-19`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ejml:0.3.0-dev-17' + implementation 'space.kscience:kmath-ejml:0.3.0-dev-19' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ejml:0.3.0-dev-17") + implementation("space.kscience:kmath-ejml:0.3.0-dev-19") } ``` diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md index 938327612..f6b02e6ad 100644 --- a/kmath-for-real/README.md +++ b/kmath-for-real/README.md @@ -9,7 +9,7 @@ Specialization of KMath APIs for Double numbers. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-17`. +The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-19`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-for-real:0.3.0-dev-17' + implementation 'space.kscience:kmath-for-real:0.3.0-dev-19' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-for-real:0.3.0-dev-17") + implementation("space.kscience:kmath-for-real:0.3.0-dev-19") } ``` diff --git a/kmath-functions/README.md b/kmath-functions/README.md index 3d4beee47..a7f4f9b6f 100644 --- a/kmath-functions/README.md +++ b/kmath-functions/README.md @@ -11,7 +11,7 @@ Functions and interpolations. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-17`. +The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-19`. **Gradle:** ```gradle @@ -21,7 +21,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-functions:0.3.0-dev-17' + implementation 'space.kscience:kmath-functions:0.3.0-dev-19' } ``` **Gradle Kotlin DSL:** @@ -32,6 +32,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-functions:0.3.0-dev-17") + implementation("space.kscience:kmath-functions:0.3.0-dev-19") } ``` diff --git a/kmath-jafama/README.md b/kmath-jafama/README.md index 760244751..3e0d9c418 100644 --- a/kmath-jafama/README.md +++ b/kmath-jafama/README.md @@ -7,7 +7,7 @@ Integration with [Jafama](https://github.com/jeffhain/jafama). ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-jafama:0.3.0-dev-17`. +The Maven coordinates of this project are `space.kscience:kmath-jafama:0.3.0-dev-19`. **Gradle:** ```gradle @@ -17,7 +17,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-jafama:0.3.0-dev-17' + implementation 'space.kscience:kmath-jafama:0.3.0-dev-19' } ``` **Gradle Kotlin DSL:** @@ -28,7 +28,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-jafama:0.3.0-dev-17") + implementation("space.kscience:kmath-jafama:0.3.0-dev-19") } ``` diff --git a/kmath-kotlingrad/README.md b/kmath-kotlingrad/README.md index 588ccb9b4..422ce4fb0 100644 --- a/kmath-kotlingrad/README.md +++ b/kmath-kotlingrad/README.md @@ -8,7 +8,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-kotlingrad:0.3.0-dev-17`. +The Maven coordinates of this project are `space.kscience:kmath-kotlingrad:0.3.0-dev-19`. **Gradle:** ```gradle @@ -18,7 +18,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-kotlingrad:0.3.0-dev-17' + implementation 'space.kscience:kmath-kotlingrad:0.3.0-dev-19' } ``` **Gradle Kotlin DSL:** @@ -29,6 +29,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-kotlingrad:0.3.0-dev-17") + implementation("space.kscience:kmath-kotlingrad:0.3.0-dev-19") } ``` diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index 7ca9cd4fd..23d529e72 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -9,7 +9,7 @@ ND4J based implementations of KMath abstractions. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-17`. +The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-19`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-nd4j:0.3.0-dev-17' + implementation 'space.kscience:kmath-nd4j:0.3.0-dev-19' } ``` **Gradle Kotlin DSL:** @@ -30,7 +30,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-nd4j:0.3.0-dev-17") + implementation("space.kscience:kmath-nd4j:0.3.0-dev-19") } ``` diff --git a/kmath-tensors/README.md b/kmath-tensors/README.md index 42ce91336..93f78e895 100644 --- a/kmath-tensors/README.md +++ b/kmath-tensors/README.md @@ -9,7 +9,7 @@ Common linear algebra operations on tensors. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.0-dev-17`. +The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.0-dev-19`. **Gradle:** ```gradle @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-tensors:0.3.0-dev-17' + implementation 'space.kscience:kmath-tensors:0.3.0-dev-19' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-tensors:0.3.0-dev-17") + implementation("space.kscience:kmath-tensors:0.3.0-dev-19") } ``` -- 2.34.1 From 93de1d53116b29391797f68972c0f6bf144857d6 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sun, 13 Mar 2022 03:27:00 +0300 Subject: [PATCH 016/275] Added support for all polynomials. But standard utilities still are not fully implemented. --- .../kmath/functions/AbstractPolynomial.kt | 47 +- .../functions/AbstractRationalFunction.kt | 2 - .../kmath/functions/LabeledPolynomial.kt | 927 ++++++++++++++++++ .../kmath/functions/NumberedPolynomial.kt | 689 +++++++++++++ .../kscience/kmath/functions/Polynomial.kt | 151 ++- .../kscience/kmath/functions/Variable.kt | 38 + .../kscience/kmath/functions/algebraicStub.kt | 51 + .../kmath/functions/labeledPolynomialUtil.kt | 490 +++++++++ .../kmath/functions/numberedPolynomialUtil.kt | 605 ++++++++++++ .../kmath/functions/polynomialUtil.kt | 6 +- 10 files changed, 2911 insertions(+), 95 deletions(-) create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Variable.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt index 237a72bcc..b7b7116f0 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt @@ -17,6 +17,9 @@ public interface AbstractPolynomial /** * 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 a coefficients in their terms. + * @param P the type of polynomials. */ @Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") public interface AbstractPolynomialSpace> : Ring

{ @@ -307,48 +310,4 @@ public interface AbstractPolynomialSpace> : Ring

override fun add(left: P, right: P): P = left + right override fun multiply(left: P, right: P): P = left * right // endregion - - public companion object { - // TODO: All of this should be moved to algebraic structures' place for utilities - // TODO: Move receiver to context receiver - /** - * Multiplication of element and integer. - * - * @receiver the multiplicand. - * @param other the multiplier. - * @return the difference. - */ - internal tailrec fun Group.optimizedMultiply(arg: C, other: Int): C = - when { - other == 0 -> zero - other == 1 -> arg - other == -1 -> -arg - other % 2 == 0 -> optimizedMultiply(arg + arg, other / 2) - other % 2 == 1 -> optimizedAddMultiplied(arg, arg + arg, other / 2) - other % 2 == -1 -> optimizedAddMultiplied(-arg, arg + arg, other / 2) - else -> error("Error in multiplication group instant by integer: got reminder by division by 2 different from 0, 1 and -1") - } - - // TODO: Move receiver to context receiver - /** - * Adds product of [arg] and [multiplier] to [base]. - * - * @receiver the algebra to provide multiplication. - * @param base the augend. - * @param arg the multiplicand. - * @param multiplier the multiplier. - * @return sum of the augend [base] and product of the multiplicand [arg] and the multiplier [multiplier]. - * @author Gleb Minaev - */ - internal tailrec fun Group.optimizedAddMultiplied(base: C, arg: C, multiplier: Int): C = - when { - multiplier == 0 -> base - multiplier == 1 -> base + arg - multiplier == -1 -> base - arg - multiplier % 2 == 0 -> optimizedAddMultiplied(base, arg + arg, multiplier / 2) - multiplier % 2 == 1 -> optimizedAddMultiplied(base + arg, arg + arg, multiplier / 2) - multiplier % 2 == -1 -> optimizedAddMultiplied(base + arg, arg + arg, multiplier / 2) - else -> error("Error in multiplication group instant by integer: got reminder by division by 2 different from 0, 1 and -1") - } - } } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt index 5cb570c9f..34050aa0f 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt @@ -5,8 +5,6 @@ package space.kscience.kmath.functions -import space.kscience.kmath.functions.AbstractPolynomialSpace.Companion.optimizedAddMultiplied -import space.kscience.kmath.functions.AbstractPolynomialSpace.Companion.optimizedMultiply import space.kscience.kmath.operations.* import kotlin.js.JsName import kotlin.jvm.JvmName diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt new file mode 100644 index 000000000..48f6f57fa --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -0,0 +1,927 @@ +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.* +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract +import kotlin.experimental.ExperimentalTypeInference +import kotlin.jvm.JvmName +import kotlin.math.max + + +/** + * Represents multivariate polynomials with labeled variables. + * + * @param C Ring in which the polynomial is considered. + */ +public class LabeledPolynomial +internal constructor( + /** + * Map that collects coefficients of the polynomial. Every non-zero monomial + * `a x_1^{d_1} ... x_n^{d_n}` is represented as pair "key-value" in the map, where value is coefficients `a` and + * key is map that associates variables in the monomial with multiplicity of them occurring in the monomial. + * For example polynomial + * ``` + * 5 a^2 c^3 - 6 b + 0 b c + * ``` + * has coefficients represented as + * ``` + * mapOf( + * mapOf( + * a to 2, + * c to 3 + * ) to 5, + * mapOf( + * b to 1 + * ) to (-6) + * ) + * ``` + * where `a`, `b` and `c` are corresponding [Variable] objects. + */ + public val coefficients: Map, C> +) : AbstractPolynomial { + override fun toString(): String = "LabeledPolynomial$coefficients" +} + +// region Internal utilities + +/** + * Represents internal [LabeledPolynomial] errors. + */ +internal class LabeledPolynomialError: Error { + constructor(): super() + constructor(message: String): super(message) + constructor(message: String?, cause: Throwable?): super(message, cause) + constructor(cause: Throwable?): super(cause) +} + +/** + * Throws an [LabeledPolynomialError] with the given [message]. + */ +internal fun labeledPolynomialError(message: Any): Nothing = throw LabeledPolynomialError(message.toString()) + +/** + * Returns the same degrees description of the monomial, but without zero degrees. + */ +internal fun Map.cleanUp() = filterValues { it > 0U } + +// endregion + +// region Constructors and converters + +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received +// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. +// * +// * @param pairs Collection of pairs that represent monomials. +// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. +// * +// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(A) +//internal fun > LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true): LabeledPolynomial { +// if (!toCheckInput) return LabeledPolynomial(coefs) +// +// // Map for cleaned coefficients. +// val fixedCoefs = mutableMapOf, C>() +// +// // Cleaning the degrees, summing monomials of the same degrees. +// for (entry in coefs) { +// val key = entry.key.cleanUp() +// val value = entry.value +// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value +// } +// +// // Removing zero monomials. +// return LabeledPolynomial( +// fixedCoefs +// .filter { it.value.isNotZero() } +// ) +//} +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received +// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. +// * +// * @param pairs Collection of pairs that represent monomials. +// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. +// * +// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(A) +//internal fun > LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean): LabeledPolynomial { +// if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) +// +// // Map for cleaned coefficients. +// val fixedCoefs = mutableMapOf, C>() +// +// // Cleaning the degrees, summing monomials of the same degrees. +// for (entry in pairs) { +// val key = entry.first.cleanUp() +// val value = entry.second +// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value +// } +// +// // Removing zero monomials. +// return LabeledPolynomial( +// fixedCoefs.filterValues { it.isNotZero() } +// ) +//} +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received +// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. +// * +// * @param pairs Collection of pairs that represents monomials. +// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. +// * +// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(A) +//internal fun > LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean): LabeledPolynomial { +// if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) +// +// // Map for cleaned coefficients. +// val fixedCoefs = mutableMapOf, C>() +// +// // Cleaning the degrees, summing monomials of the same degrees. +// for (entry in pairs) { +// val key = entry.first.cleanUp() +// val value = entry.second +// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value +// } +// +// // Removing zero monomials. +// return LabeledPolynomial( +// fixedCoefs.filterValues { it.isNotZero() } +// ) +//} +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received +// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. +// * +// * @param coefs Coefficients of the instants. +// * +// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(A) +//fun > LabeledPolynomial(coefs: Map, C>): LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received +// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. +// * +// * @param pairs Collection of pairs that represents monomials. +// * +// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(A) +//fun > LabeledPolynomial(pairs: Collection, C>>): LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received +// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. +// * +// * @param pairs Collection of pairs that represents monomials. +// * +// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(A) +//fun > LabeledPolynomial(vararg pairs: Pair, C>): LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received +// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. +// * +// * @param pairs Collection of pairs that represent monomials. +// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. +// * +// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(LabeledPolynomialSpace) +//internal fun > LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true): LabeledPolynomial { +// if (!toCheckInput) return LabeledPolynomial(coefs) +// +// // Map for cleaned coefficients. +// val fixedCoefs = mutableMapOf, C>() +// +// // Cleaning the degrees, summing monomials of the same degrees. +// for (entry in coefs) { +// val key = entry.key.cleanUp() +// val value = entry.value +// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value +// } +// +// // Removing zero monomials. +// return LabeledPolynomial( +// fixedCoefs +// .filter { it.value.isNotZero() } +// ) +//} +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received +// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. +// * +// * @param pairs Collection of pairs that represent monomials. +// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. +// * +// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(LabeledPolynomialSpace) +//internal fun > LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean): LabeledPolynomial { +// if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) +// +// // Map for cleaned coefficients. +// val fixedCoefs = mutableMapOf, C>() +// +// // Cleaning the degrees, summing monomials of the same degrees. +// for (entry in pairs) { +// val key = entry.first.cleanUp() +// val value = entry.second +// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value +// } +// +// // Removing zero monomials. +// return LabeledPolynomial( +// fixedCoefs.filterValues { it.isNotZero() } +// ) +//} +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received +// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. +// * +// * @param pairs Collection of pairs that represents monomials. +// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. +// * +// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(LabeledPolynomialSpace) +//internal fun > LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean): LabeledPolynomial { +// if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) +// +// // Map for cleaned coefficients. +// val fixedCoefs = mutableMapOf, C>() +// +// // Cleaning the degrees, summing monomials of the same degrees. +// for (entry in pairs) { +// val key = entry.first.cleanUp() +// val value = entry.second +// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value +// } +// +// // Removing zero monomials. +// return LabeledPolynomial( +// fixedCoefs.filterValues { it.isNotZero() } +// ) +//} +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received +// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. +// * +// * @param coefs Coefficients of the instants. +// * +// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(LabeledPolynomialSpace) +//fun > LabeledPolynomial(coefs: Map, C>): LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received +// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. +// * +// * @param pairs Collection of pairs that represents monomials. +// * +// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(LabeledPolynomialSpace) +//fun > LabeledPolynomial(pairs: Collection, C>>): LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received +// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. +// * +// * @param pairs Collection of pairs that represents monomials. +// * +// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(LabeledPolynomialSpace) +//fun > LabeledPolynomial(vararg pairs: Pair, C>): LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) +// +//fun C.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to this)) +// +//context(A) +//fun > Variable.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1U) to one)) +// +//context(LabeledPolynomialSpace) +//fun > Variable.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1U) to ring.one)) +// +//context(A) +//fun > Variable.asLabeledPolynomial(c: C) : LabeledPolynomial = +// if(c.isZero()) LabeledPolynomial(emptyMap()) +// else LabeledPolynomial(mapOf(mapOf(this to 1U) to c)) +// +//context(LabeledPolynomialSpace) +//fun > Variable.asLabeledPolynomial(c: C) : LabeledPolynomial = +// if(c.isZero()) zero +// else LabeledPolynomial(mapOf(mapOf(this to 1U) to c)) + +// endregion + +/** + * Space of polynomials. + * + * @param C the type of operated polynomials. + * @param A the intersection of [Ring] of [C] and [ScaleOperations] of [C]. + * @param ring the [A] instance. + */ +@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE", "INAPPLICABLE_JVM_NAME") +public class LabeledPolynomialSpace>( + public val ring: A, +) : AbstractPolynomialSpace> { + // region Constant-integer relation + @JvmName("constantIntPlus") + public override operator fun C.plus(other: Int): C = ring { optimizedAddMultiplied(this@plus, one, other) } + @JvmName("constantIntMinus") + public override operator fun C.minus(other: Int): C = ring { optimizedAddMultiplied(this@minus, one, -other) } + @JvmName("constantIntTimes") + public override operator fun C.times(other: Int): C = ring { optimizedMultiply(this@times, other) } + // endregion + + // region Integer-constant relation + @JvmName("intConstantPlus") + public override operator fun Int.plus(other: C): C = ring { optimizedAddMultiplied(other, one, this@plus) } + @JvmName("intConstantMinus") + public override operator fun Int.minus(other: C): C = ring { optimizedAddMultiplied(-other, one, this@minus) } + @JvmName("intConstantTimes") + public override operator fun Int.times(other: C): C = ring { optimizedMultiply(other, this@times) } + // endregion + + // region Variable-integer relation + public operator fun Variable.plus(other: Int): LabeledPolynomial = + if (other == 0) LabeledPolynomial(mapOf( + mapOf(this@plus to 1U) to ring.one, + )) + else LabeledPolynomial(mapOf( + mapOf(this@plus to 1U) to ring.one, + emptyMap() to ring.one * other, + )) + public operator fun Variable.minus(other: Int): LabeledPolynomial = + if (other == 0) LabeledPolynomial(mapOf( + mapOf(this@minus to 1U) to -ring.one, + )) + else LabeledPolynomial(mapOf( + mapOf(this@minus to 1U) to -ring.one, + emptyMap() to ring.one * other, + )) + public operator fun Variable.times(other: Int): LabeledPolynomial = + if (other == 0) zero + else LabeledPolynomial(mapOf( + mapOf(this to 1U) to ring.one * other, + )) + // endregion + + // region Integer-variable relation + public operator fun Int.plus(other: Variable): LabeledPolynomial = + if (this == 0) LabeledPolynomial(mapOf( + mapOf(other to 1U) to ring.one, + )) + else LabeledPolynomial(mapOf( + mapOf(other to 1U) to ring.one, + emptyMap() to ring.one * this@plus, + )) + public operator fun Int.minus(other: Variable): LabeledPolynomial = + if (this == 0) LabeledPolynomial(mapOf( + mapOf(other to 1U) to -ring.one, + )) + else LabeledPolynomial(mapOf( + mapOf(other to 1U) to -ring.one, + emptyMap() to ring.one * this@minus, + )) + public operator fun Int.times(other: Variable): LabeledPolynomial = + if (this == 0) zero + else LabeledPolynomial(mapOf( + mapOf(other to 1U) to ring.one * this@times, + )) + // endregion + + // region Polynomial-integer relation + public override operator fun LabeledPolynomial.plus(other: Int): LabeledPolynomial = + if (other == 0) this + else + LabeledPolynomial( + coefficients + .toMutableMap() + .apply { + val degs = emptyMap() + + val result = getOrElse(degs) { ring.zero } + other + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + public override operator fun LabeledPolynomial.minus(other: Int): LabeledPolynomial = + if (other == 0) this + else + LabeledPolynomial( + coefficients + .toMutableMap() + .apply { + val degs = emptyMap() + + val result = getOrElse(degs) { ring.zero } - other + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + public override operator fun LabeledPolynomial.times(other: Int): LabeledPolynomial = + if (other == 0) zero + else LabeledPolynomial( + coefficients + .applyAndRemoveZeros { + mapValues { (_, c) -> c * other } + } + ) + // endregion + + // region Integer-polynomial relation + public override operator fun Int.plus(other: LabeledPolynomial): LabeledPolynomial = + if (this == 0) other + else + LabeledPolynomial( + other.coefficients + .toMutableMap() + .apply { + val degs = emptyMap() + + val result = this@plus + getOrElse(degs) { ring.zero } + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + public override operator fun Int.minus(other: LabeledPolynomial): LabeledPolynomial = + if (this == 0) other + else + LabeledPolynomial( + other.coefficients + .toMutableMap() + .apply { + val degs = emptyMap() + + val result = this@minus - getOrElse(degs) { ring.zero } + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + public override operator fun Int.times(other: LabeledPolynomial): LabeledPolynomial = + if (this == 0) zero + else LabeledPolynomial( + other.coefficients + .applyAndRemoveZeros { + mapValues { (_, c) -> this@times * c } + } + ) + // endregion + + // region Constant-constant relation + @JvmName("constantUnaryMinus") + override operator fun C.unaryMinus(): C = ring { -this@unaryMinus } + @JvmName("constantPlus") + override operator fun C.plus(other: C): C = ring { this@plus + other } + @JvmName("constantMinus") + override operator fun C.minus(other: C): C = ring { this@minus - other } + @JvmName("constantTimes") + override operator fun C.times(other: C): C = ring { this@times * other } + @JvmName("constantIsZero") + public override fun C.isZero(): Boolean = ring { this == zero } + @JvmName("constantIsNotZero") + public override fun C.isNotZero(): Boolean = ring { this != zero } + @JvmName("constantIsOne") + public override fun C.isOne(): Boolean = ring { this == one } + @JvmName("constantIsNotOne") + public override fun C.isNotOne(): Boolean = ring { this != one } + @JvmName("constantIsMinusOne") + public override fun C.isMinusOne(): Boolean = ring { this == -one } + @JvmName("constantIsNotMinusOne") + public override fun C.isNotMinusOne(): Boolean = ring { this != -one } + // endregion + + // region Constant-variable relation + public operator fun C.plus(other: Variable): LabeledPolynomial = + if (isZero()) LabeledPolynomial(mapOf( + mapOf(other to 1U) to ring.one, + )) + else LabeledPolynomial(mapOf( + mapOf(other to 1U) to ring.one, + emptyMap() to this@plus, + )) + public operator fun C.minus(other: Variable): LabeledPolynomial = + if (isZero()) LabeledPolynomial(mapOf( + mapOf(other to 1U) to -ring.one, + )) + else LabeledPolynomial(mapOf( + mapOf(other to 1U) to -ring.one, + emptyMap() to this@minus, + )) + public operator fun C.times(other: Variable): LabeledPolynomial = + if (isZero()) zero + else LabeledPolynomial(mapOf( + mapOf(other to 1U) to this@times, + )) + // endregion + + // region Variable-constant relation + public operator fun Variable.plus(other: C): LabeledPolynomial = + if (other.isZero()) LabeledPolynomial(mapOf( + mapOf(this@plus to 1U) to ring.one, + )) + else LabeledPolynomial(mapOf( + mapOf(this@plus to 1U) to ring.one, + emptyMap() to other, + )) + public operator fun Variable.minus(other: C): LabeledPolynomial = + if (other.isZero()) LabeledPolynomial(mapOf( + mapOf(this@minus to 1U) to -ring.one, + )) + else LabeledPolynomial(mapOf( + mapOf(this@minus to 1U) to -ring.one, + emptyMap() to other, + )) + public operator fun Variable.times(other: C): LabeledPolynomial = + if (other.isZero()) zero + else LabeledPolynomial(mapOf( + mapOf(this@times to 1U) to other, + )) + // endregion + + // region Constant-polynomial relation + override operator fun C.plus(other: LabeledPolynomial): LabeledPolynomial = + if (this.isZero()) other + else with(other.coefficients) { + if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@plus)) + else LabeledPolynomial( + toMutableMap() + .apply { + val degs = emptyMap() + + val result = this@plus + getOrElse(degs) { ring.zero } + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + } + override operator fun C.minus(other: LabeledPolynomial): LabeledPolynomial = + if (this.isZero()) other + else with(other.coefficients) { + if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@minus)) + else LabeledPolynomial( + toMutableMap() + .apply { + forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } + + val degs = emptyMap() + + val result = this@minus - getOrElse(degs) { ring.zero } + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + } + override operator fun C.times(other: LabeledPolynomial): LabeledPolynomial = + if (this.isZero()) zero + else LabeledPolynomial( + other.coefficients + .applyAndRemoveZeros { + mapValues { (_, c) -> this@times * c } + } + ) + // endregion + + // region Polynomial-constant relation + /** + * Returns sum of the polynomials. [other] is interpreted as [UnivariatePolynomial]. + */ + override operator fun LabeledPolynomial.plus(other: C): LabeledPolynomial = + if (other.isZero()) this + else with(coefficients) { + if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to other)) + else LabeledPolynomial( + toMutableMap() + .apply { + val degs = emptyMap() + + val result = getOrElse(degs) { ring.zero } + other + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + } + /** + * Returns difference of the polynomials. [other] is interpreted as [UnivariatePolynomial]. + */ + override operator fun LabeledPolynomial.minus(other: C): LabeledPolynomial = + if (other.isZero()) this + else with(coefficients) { + if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to other)) + else LabeledPolynomial( + toMutableMap() + .apply { + forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } + + val degs = emptyMap() + + val result = getOrElse(degs) { ring.zero } - other + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + } + /** + * Returns product of the polynomials. [other] is interpreted as [UnivariatePolynomial]. + */ + override operator fun LabeledPolynomial.times(other: C): LabeledPolynomial = + if (other.isZero()) zero + else LabeledPolynomial( + coefficients + .applyAndRemoveZeros { + mapValues { (_, c) -> c * other } + } + ) + // endregion + + // region Variable-variable relation + public operator fun Variable.plus(other: Variable): LabeledPolynomial = + if (this == other) LabeledPolynomial(mapOf( + mapOf(this to 1U) to ring.one * 2 + )) + else LabeledPolynomial(mapOf( + mapOf(this to 1U) to ring.one, + mapOf(other to 1U) to ring.one, + )) + public operator fun Variable.minus(other: Variable): LabeledPolynomial = + if (this == other) zero + else LabeledPolynomial(mapOf( + mapOf(this to 1U) to ring.one, + mapOf(other to 1U) to -ring.one, + )) + public operator fun Variable.times(other: Variable): LabeledPolynomial = + if (this == other) LabeledPolynomial(mapOf( + mapOf(this to 2U) to ring.one + )) + else LabeledPolynomial(mapOf( + mapOf(this to 1U, other to 1U) to ring.one, + )) + // endregion + + // region Variable-polynomial relation + public operator fun Variable.plus(other: LabeledPolynomial): LabeledPolynomial = + with(other.coefficients) { + if (isEmpty()) LabeledPolynomial(mapOf(mapOf(this@plus to 1u) to ring.one)) + else LabeledPolynomial( + toMutableMap() + .apply { + val degs = mapOf(this@plus to 1U) + + val result = ring.one + getOrElse(degs) { ring.zero } + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + } + public operator fun Variable.minus(other: LabeledPolynomial): LabeledPolynomial = + with(other.coefficients) { + if (isEmpty()) LabeledPolynomial(mapOf(mapOf(this@minus to 1u) to ring.one)) + else LabeledPolynomial( + toMutableMap() + .apply { + forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } + + val degs = mapOf(this@minus to 1U) + + val result = ring.one - getOrElse(degs) { ring.zero } + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + } + public operator fun Variable.times(other: LabeledPolynomial): LabeledPolynomial = + LabeledPolynomial( + other.coefficients + .mapKeys { (degs, _) -> degs.toMutableMap().also{ it[this] = if (this in it) it[this]!! + 1U else 1U } } + ) + // endregion + + // region Polynomial-variable relation + public operator fun LabeledPolynomial.plus(other: Variable): LabeledPolynomial = + with(coefficients) { + if (isEmpty()) LabeledPolynomial(mapOf(mapOf(other to 1u) to ring.one)) + else LabeledPolynomial( + toMutableMap() + .apply { + val degs = mapOf(other to 1U) + + val result = ring.one + getOrElse(degs) { ring.zero } + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + } + public operator fun LabeledPolynomial.minus(other: Variable): LabeledPolynomial = + with(coefficients) { + if (isEmpty()) LabeledPolynomial(mapOf(mapOf(other to 1u) to ring.one)) + else LabeledPolynomial( + toMutableMap() + .apply { + val degs = mapOf(other to 1U) + + val result = ring.one - getOrElse(degs) { ring.zero } + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + } + public operator fun LabeledPolynomial.times(other: Variable): LabeledPolynomial = + LabeledPolynomial( + coefficients + .mapKeys { (degs, _) -> degs.toMutableMap().also{ it[other] = if (other in it) it[other]!! + 1U else 1U } } + ) + // endregion + + // region Polynomial-polynomial relation + /** + * Returns negation of the polynomial. + */ + override fun LabeledPolynomial.unaryMinus(): LabeledPolynomial = + LabeledPolynomial( + coefficients.mapValues { -it.value } + ) + /** + * Returns sum of the polynomials. + */ + override operator fun LabeledPolynomial.plus(other: LabeledPolynomial): LabeledPolynomial = + LabeledPolynomial( + coefficients + .applyAndRemoveZeros { + other.coefficients + .mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value } + } + ) + /** + * Returns difference of the polynomials. + */ + override operator fun LabeledPolynomial.minus(other: LabeledPolynomial): LabeledPolynomial = + LabeledPolynomial( + coefficients + .applyAndRemoveZeros { + other.coefficients + .mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value } + } + ) + /** + * Returns product of the polynomials. + */ + override operator fun LabeledPolynomial.times(other: LabeledPolynomial): LabeledPolynomial = + when { + isZero() -> zero + other.isZero() -> zero + else -> LabeledPolynomial( + buildCoefficients { + for ((degs1, c1) in coefficients) for ((degs2, c2) in other.coefficients) { + val degs = degs1.toMutableMap() + degs2.mapValuesTo(degs) { (variable, deg) -> degs.getOrElse(variable) { 0u } + deg } + val c = c1 * c2 + this[degs] = if (degs in this) this[degs]!! + c else c + } + } + ) + } + + override val zero: LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to ring.zero)) + override val one: LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to ring.one)) + + // TODO: Docs + @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") + override fun LabeledPolynomial.equals(other: LabeledPolynomial): Boolean = + when { + this === other -> true + else -> coefficients.size == other.coefficients.size && + coefficients.all { (key, value) -> with(other.coefficients) { key in this && this[key] == value } } + } + // endregion + + // Not sure is it necessary... + // region Polynomial properties + /** + * 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, c) -> if (c.isZero()) -1 else 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 val LabeledPolynomial.degrees: Map + get() = + buildMap { + coefficients.entries.forEach { (degs, c) -> + if (c.isNotZero()) degs.mapValuesTo(this) { (variable, deg) -> + max(getOrElse(variable) { 0u }, deg) + } + } + } + /** + * Set of all variables that appear in the polynomial in positive exponents. + */ + public val LabeledPolynomial.variables: Set + get() = + buildSet { + coefficients.entries.forEach { (degs, c) -> if (c.isNotZero()) addAll(degs.keys) } + } + /** + * Count of all variables that appear in the polynomial in positive exponents. + */ + public val LabeledPolynomial.countOfVariables: Int get() = variables.size + + /** + * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. + */ + override fun LabeledPolynomial.isConstant(): Boolean = + coefficients.all { (degs, c) -> degs.isEmpty() || c.isZero() } + /** + * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. + */ + override fun LabeledPolynomial.isNonZeroConstant(): Boolean = + with(coefficients) { + var foundAbsoluteTermAndItIsNotZero = false + for ((degs, c) in this) { + if (degs.isNotEmpty()) if (c.isNotZero()) return@with false + else { + if (c.isZero()) return@with false + else foundAbsoluteTermAndItIsNotZero = true + } + } + foundAbsoluteTermAndItIsNotZero + } + + override fun LabeledPolynomial.asConstantOrNull(): C? = + with(coefficients) { + if(isConstant()) getOrElse(emptyMap()) { ring.zero } + else null + } + +// @Suppress("NOTHING_TO_INLINE") +// public inline fun LabeledPolynomial.substitute(argument: Map): LabeledPolynomial = this.substitute(ring, argument) +// @Suppress("NOTHING_TO_INLINE") +// @JvmName("substitutePolynomial") +// public inline fun LabeledPolynomial.substitute(argument: Map>): LabeledPolynomial = this.substitute(ring, argument) +// +// @Suppress("NOTHING_TO_INLINE") +// public inline fun LabeledPolynomial.asFunction(): (Map) -> LabeledPolynomial = { this.substitute(ring, it) } +// @Suppress("NOTHING_TO_INLINE") +// public inline fun LabeledPolynomial.asFunctionOnConstants(): (Map) -> LabeledPolynomial = { this.substitute(ring, it) } +// @Suppress("NOTHING_TO_INLINE") +// public inline fun LabeledPolynomial.asFunctionOnPolynomials(): (Map>) -> LabeledPolynomial = { this.substitute(ring, it) } +// +// @Suppress("NOTHING_TO_INLINE") +// public inline operator fun LabeledPolynomial.invoke(argument: Map): LabeledPolynomial = this.substitute(ring, argument) +// @Suppress("NOTHING_TO_INLINE") +// @JvmName("invokePolynomial") +// public inline operator fun LabeledPolynomial.invoke(argument: Map>): LabeledPolynomial = this.substitute(ring, argument) + // endregion + + // region Legacy + @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") + override inline fun add(left: LabeledPolynomial, right: LabeledPolynomial): LabeledPolynomial = left + right + @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") + override inline fun multiply(left: LabeledPolynomial, right: LabeledPolynomial): LabeledPolynomial = left * right + // endregion + + // region Utilities + // TODO: Move to region internal utilities with context receiver + internal fun MutableMap, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : MutableMap, C> { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + block() + for ((degs, c) in this) if (c.isZero()) this.remove(degs) + return this + } + internal fun Map, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : Map, C> = + toMutableMap().applyAndRemoveZeros(block) + @OptIn(ExperimentalTypeInference::class) + internal fun buildCoefficients(@BuilderInference builderAction: MutableMap, C>.() -> Unit): Map, C> { + contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } + return buildMap { + builderAction() + for ((degs, c) in this) if (c.isZero()) this.remove(degs) + } + } + // endregion +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt new file mode 100644 index 000000000..f1ad9a74f --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -0,0 +1,689 @@ +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.* +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract +import kotlin.experimental.ExperimentalTypeInference +import kotlin.jvm.JvmName +import kotlin.math.max + + +/** + * Polynomial model without fixation on specific context they are applied to. + * + * @param C the type of constants. + */ +public class NumberedPolynomial +internal constructor( + /** + * Map that collects coefficients of the polynomial. Every monomial `a x_1^{d_1} ... x_n^{d_n}` is represented as + * pair "key-value" in the map, where value is coefficients `a` and + * key is list that associates index of every variable in the monomial with multiplicity of the variable occurring + * in the monomial. For example coefficients of polynomial `5 x_1^2 x_3^3 - 6 x_2` can be represented as + * ``` + * mapOf( + * listOf(2, 0, 3) to 5, + * listOf(0, 1) to (-6), + * ) + * ``` + * and also as + * ``` + * mapOf( + * listOf(2, 0, 3) to 5, + * listOf(0, 1) to (-6), + * listOf(0, 1, 1) to 0, + * ) + * ``` + * It is recommended not to put zero monomials into the map, but is not prohibited. Lists of degrees always do not + * contain any zeros on end, but can contain zeros on start or anywhere in middle. + */ + public val coefficients: Map, C> +) : AbstractPolynomial { + override fun toString(): String = "NumberedPolynomial$coefficients" +} + +// region Internal utilities + +/** + * Represents internal [Polynomial] errors. + */ +internal class NumberedPolynomialError : Error { + constructor(): super() + constructor(message: String): super(message) + constructor(message: String?, cause: Throwable?): super(message, cause) + constructor(cause: Throwable?): super(cause) +} + +/** + * Throws an [PolynomialError] with the given [message]. + */ +internal fun numberedPolynomialError(message: Any): Nothing = throw PolynomialError(message.toString()) + +/** + * 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) + +// endregion + +// region Constructors and converters +// Waiting for context receivers :( TODO: Replace with context receivers when they will be available + +//context(A) +//@Suppress("FunctionName") +//internal fun > NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean): NumberedPolynomial { +// if (!toCheckInput) return NumberedPolynomial(coefs) +// +// val fixedCoefs = mutableMapOf, C>() +// +// for (entry in coefs) { +// val key = entry.key.cleanUp() +// val value = entry.value +// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value +// } +// +// return NumberedPolynomial( +// fixedCoefs +// .filter { it.value.isNotZero() } +// ) +//} +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received +// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. +// * +// * @param pairs Collection of pairs that represent monomials. +// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. +// * +// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(A) +//@Suppress("FunctionName") +//internal fun > NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean): NumberedPolynomial { +// if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) +// +// val fixedCoefs = mutableMapOf, C>() +// +// for (entry in pairs) { +// val key = entry.first.cleanUp() +// val value = entry.second +// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value +// } +// +// return NumberedPolynomial( +// fixedCoefs +// .filter { it.value.isNotZero() } +// ) +//} +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received +// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. +// * +// * @param pairs Collection of pairs that represent monomials. +// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. +// * +// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(A) +//@Suppress("FunctionName") +//internal fun > NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean): NumberedPolynomial = +// NumberedPolynomial(pairs.toMap(), toCheckInput) +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received +// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. +// * +// * @param coefs Coefficients of the instants. +// * +// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(A) +//public fun > NumberedPolynomial(coefs: Map, C>) = NumberedPolynomial(coefs, toCheckInput = true) +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received +// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. +// * +// * @param pairs Collection of pairs that represent monomials. +// * +// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(A) +//public fun > NumberedPolynomial(pairs: Collection, C>>) = NumberedPolynomial(pairs, toCheckInput = true) +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received +// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. +// * +// * @param pairs Collection of pairs that represent monomials. +// * +// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(A) +//public fun > NumberedPolynomial(vararg pairs: Pair, C>) = NumberedPolynomial(*pairs, toCheckInput = true) +// +//context(NumberedPolynomialSpace) +//@Suppress("FunctionName") +//internal fun > NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean): NumberedPolynomial { +// if (!toCheckInput) return NumberedPolynomial(coefs) +// +// val fixedCoefs = mutableMapOf, C>() +// +// for (entry in coefs) { +// val key = entry.key.cleanUp() +// val value = entry.value +// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value +// } +// +// return NumberedPolynomial( +// fixedCoefs +// .filter { it.value.isNotZero() } +// ) +//} +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received +// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. +// * +// * @param pairs Collection of pairs that represent monomials. +// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. +// * +// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(NumberedPolynomialSpace) +//@Suppress("FunctionName") +//internal fun > NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean): NumberedPolynomial { +// if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) +// +// val fixedCoefs = mutableMapOf, C>() +// +// for (entry in pairs) { +// val key = entry.first.cleanUp() +// val value = entry.second +// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value +// } +// +// return NumberedPolynomial( +// fixedCoefs +// .filter { it.value.isNotZero() } +// ) +//} +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received +// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. +// * +// * @param pairs Collection of pairs that represent monomials. +// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. +// * +// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(NumberedPolynomialSpace) +//@Suppress("FunctionName") +//internal fun > NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean): NumberedPolynomial = +// NumberedPolynomial(pairs.toList(), toCheckInput) +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received +// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. +// * +// * @param coefs Coefficients of the instants. +// * +// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(NumberedPolynomialSpace) +//public fun > NumberedPolynomial(coefs: Map, C>) = NumberedPolynomial(coefs, toCheckInput = true) +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received +// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. +// * +// * @param pairs Collection of pairs that represent monomials. +// * +// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(NumberedPolynomialSpace) +//public fun > NumberedPolynomial(pairs: Collection, C>>) = NumberedPolynomial(pairs, toCheckInput = true) +///** +// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received +// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. +// * +// * @param pairs Collection of pairs that represent monomials. +// * +// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. +// */ +//context(NumberedPolynomialSpace) +//public fun > NumberedPolynomial(vararg pairs: Pair, C>) = NumberedPolynomial(*pairs, toCheckInput = true) + +public fun > C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(emptyList() to this)) + +// endregion + +/** + * Space of polynomials. + * + * @param C the type of operated polynomials. + * @param A the intersection of [Ring] of [C] and [ScaleOperations] of [C]. + * @param ring the [A] instance. + */ +@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE", "INAPPLICABLE_JVM_NAME") +public class NumberedPolynomialSpace>( + public val ring: A, +) : AbstractPolynomialSpace> { + // region Constant-integer relation + @JvmName("constantIntPlus") + public override operator fun C.plus(other: Int): C = ring { optimizedAddMultiplied(this@plus, one, other) } + @JvmName("constantIntMinus") + public override operator fun C.minus(other: Int): C = ring { optimizedAddMultiplied(this@minus, one, -other) } + @JvmName("constantIntTimes") + public override operator fun C.times(other: Int): C = ring { optimizedMultiply(this@times, other) } + // endregion + + // region Integer-constant relation + @JvmName("intConstantPlus") + public override operator fun Int.plus(other: C): C = ring { optimizedAddMultiplied(other, one, this@plus) } + @JvmName("intConstantMinus") + public override operator fun Int.minus(other: C): C = ring { optimizedAddMultiplied(-other, one, this@minus) } + @JvmName("intConstantTimes") + public override operator fun Int.times(other: C): C = ring { optimizedMultiply(other, this@times) } + // endregion + + // region Polynomial-integer relation + public override operator fun NumberedPolynomial.plus(other: Int): NumberedPolynomial = + if (other == 0) this + else + NumberedPolynomial( + coefficients + .toMutableMap() + .apply { + val degs = emptyList() + + val result = getOrElse(degs) { ring.zero } + other + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + public override operator fun NumberedPolynomial.minus(other: Int): NumberedPolynomial = + if (other == 0) this + else + NumberedPolynomial( + coefficients + .toMutableMap() + .apply { + val degs = emptyList() + + val result = getOrElse(degs) { ring.zero } - other + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + public override operator fun NumberedPolynomial.times(other: Int): NumberedPolynomial = + if (other == 0) zero + else NumberedPolynomial( + coefficients + .applyAndRemoveZeros { + mapValues { (_, c) -> c * other } + } + ) + // endregion + + // region Integer-polynomial relation + public override operator fun Int.plus(other: NumberedPolynomial): NumberedPolynomial = + if (this == 0) other + else + NumberedPolynomial( + other.coefficients + .toMutableMap() + .apply { + val degs = emptyList() + + val result = this@plus + getOrElse(degs) { ring.zero } + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + public override operator fun Int.minus(other: NumberedPolynomial): NumberedPolynomial = + if (this == 0) other + else + NumberedPolynomial( + other.coefficients + .toMutableMap() + .apply { + val degs = emptyList() + + val result = this@minus - getOrElse(degs) { ring.zero } + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + public override operator fun Int.times(other: NumberedPolynomial): NumberedPolynomial = + if (this == 0) zero + else NumberedPolynomial( + other.coefficients + .applyAndRemoveZeros { + mapValues { (_, c) -> this@times * c } + } + ) + // endregion + + // region Constant-constant relation + @JvmName("constantUnaryMinus") + override operator fun C.unaryMinus(): C = ring { -this@unaryMinus } + @JvmName("constantPlus") + override operator fun C.plus(other: C): C = ring { this@plus + other } + @JvmName("constantMinus") + override operator fun C.minus(other: C): C = ring { this@minus - other } + @JvmName("constantTimes") + override operator fun C.times(other: C): C = ring { this@times * other } + @JvmName("constantIsZero") + public override fun C.isZero(): Boolean = ring { this == zero } + @JvmName("constantIsNotZero") + public override fun C.isNotZero(): Boolean = ring { this != zero } + @JvmName("constantIsOne") + public override fun C.isOne(): Boolean = ring { this == one } + @JvmName("constantIsNotOne") + public override fun C.isNotOne(): Boolean = ring { this != one } + @JvmName("constantIsMinusOne") + public override fun C.isMinusOne(): Boolean = ring { this == -one } + @JvmName("constantIsNotMinusOne") + public override fun C.isNotMinusOne(): Boolean = ring { this != -one } + // endregion + + // region Constant-polynomial relation + override operator fun C.plus(other: NumberedPolynomial): NumberedPolynomial = + if (this.isZero()) other + else with(other.coefficients) { + if (isEmpty()) NumberedPolynomial(mapOf(emptyList() to this@plus)) + else NumberedPolynomial( + toMutableMap() + .apply { + val degs = emptyList() + + val result = this@plus + getOrElse(degs) { ring.zero } + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + } + override operator fun C.minus(other: NumberedPolynomial): NumberedPolynomial = + if (this.isZero()) -other + else with(other.coefficients) { + if (isEmpty()) NumberedPolynomial(mapOf(listOf() to this@minus)) + else NumberedPolynomial( + toMutableMap() + .apply { + forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } + + val degs = emptyList() + + val result = this@minus - getOrElse(degs) { ring.zero } + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + } + override operator fun C.times(other: NumberedPolynomial): NumberedPolynomial = + if (this.isZero()) zero + else NumberedPolynomial( + other.coefficients + .applyAndRemoveZeros { + mapValues { (_, c) -> this@times * c } + } + ) + // endregion + + // region Polynomial-constant relation + /** + * Returns sum of the polynomials. [other] is interpreted as [NumberedPolynomial]. + */ + override operator fun NumberedPolynomial.plus(other: C): NumberedPolynomial = + if (other.isZero()) this + else with(coefficients) { + if (isEmpty()) NumberedPolynomial(mapOf(listOf() to other)) + else NumberedPolynomial( + toMutableMap() + .apply { + val degs = emptyList() + + val result = getOrElse(degs) { ring.zero } + other + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + } + /** + * Returns difference of the polynomials. [other] is interpreted as [NumberedPolynomial]. + */ + override operator fun NumberedPolynomial.minus(other: C): NumberedPolynomial = + if (other.isZero()) this + else with(coefficients) { + if (isEmpty()) NumberedPolynomial(mapOf(listOf() to other)) + else NumberedPolynomial( + toMutableMap() + .apply { + val degs = emptyList() + + val result = getOrElse(degs) { ring.zero } - other + + if (result.isZero()) remove(degs) + else this[degs] = result + } + ) + } + /** + * Returns product of the polynomials. [other] is interpreted as [NumberedPolynomial]. + */ + override operator fun NumberedPolynomial.times(other: C): NumberedPolynomial = + if (other.isZero()) zero + else NumberedPolynomial( + coefficients + .applyAndRemoveZeros { + mapValues { (_, c) -> c * other } + } + ) + // endregion + + // region Polynomial-polynomial relation + /** + * Returns negation of the polynomial. + */ + override fun NumberedPolynomial.unaryMinus(): NumberedPolynomial = + NumberedPolynomial( + coefficients.mapValues { -it.value } + ) + /** + * Returns sum of the polynomials. + */ + override operator fun NumberedPolynomial.plus(other: NumberedPolynomial): NumberedPolynomial = + NumberedPolynomial( + coefficients + .applyAndRemoveZeros { + other.coefficients + .mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value } + } + ) + /** + * Returns difference of the polynomials. + */ + override operator fun NumberedPolynomial.minus(other: NumberedPolynomial): NumberedPolynomial = + NumberedPolynomial( + coefficients + .applyAndRemoveZeros { + other.coefficients + .mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value } + } + ) + /** + * Returns product of the polynomials. + */ + override operator fun NumberedPolynomial.times(other: NumberedPolynomial): NumberedPolynomial = + when { + isZero() -> zero + other.isZero() -> zero + else -> + NumberedPolynomial( + buildCoefficients { + 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 + this[degs] = if (degs in this) this[degs]!! + c else c + } + } + ) + } + + public override fun NumberedPolynomial.isZero(): Boolean = coefficients.values.all { it.isZero() } + public override fun NumberedPolynomial.isNotZero(): Boolean = coefficients.values.any { it.isNotZero() } + public override fun NumberedPolynomial.isOne(): Boolean = + with(coefficients) { + var foundAbsoluteTermAndItIsOne = false + for ((degs, c) in this) { + if (degs.isNotEmpty()) if (c.isNotZero()) return@with false + else { + if (c.isNotOne()) return@with false + else foundAbsoluteTermAndItIsOne = true + } + } + foundAbsoluteTermAndItIsOne + } + public override fun NumberedPolynomial.isNotOne(): Boolean = !isOne() + public override fun NumberedPolynomial.isMinusOne(): Boolean = + with(coefficients) { + var foundAbsoluteTermAndItIsMinusOne = false + for ((degs, c) in this) { + if (degs.isNotEmpty()) if (c.isNotZero()) return@with false + else { + if (c.isNotMinusOne()) return@with false + else foundAbsoluteTermAndItIsMinusOne = true + } + } + foundAbsoluteTermAndItIsMinusOne + } + public override fun NumberedPolynomial.isNotMinusOne(): Boolean = !isMinusOne() + + override val zero: NumberedPolynomial = NumberedPolynomial(emptyMap()) + override val one: NumberedPolynomial = + NumberedPolynomial( + mapOf( + listOf() to ring.one // 1 * x_1^0 * x_2^0 * ... + ) + ) + + // TODO: Docs + @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") + override fun NumberedPolynomial.equals(other: NumberedPolynomial): Boolean = + when { + this === other -> true + else -> coefficients.size == other.coefficients.size && + coefficients.all { (key, value) -> with(other.coefficients) { key in this && this[key] == value } } + } + // endregion + + // Not sure is it necessary... + // region Polynomial properties + /** + * Count of all variables that appear in the polynomial in positive exponents. + */ + public val NumberedPolynomial.countOfVariables: Int + get() = coefficients.entries.maxOfOrNull { (degs, c) -> if (c.isZero()) 0 else degs.size } ?: 0 + /** + * 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.entries.maxOfOrNull { (degs, c) -> if (c.isZero()) -1 else 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 size of the list is [countOfVariables]. + */ + public val NumberedPolynomial.degrees: List + get() = + buildList(countOfVariables) { + repeat(countOfVariables) { add(0U) } + coefficients.entries.forEach { (degs, c) -> + if (c.isNotZero()) degs.forEachIndexed { index, deg -> + this[index] = max(this[index], deg) + } + } + } + + /** + * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. + */ + override fun NumberedPolynomial.isConstant(): Boolean = + coefficients.all { (degs, c) -> degs.isEmpty() || c.isZero() } + /** + * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. + */ + override fun NumberedPolynomial.isNonZeroConstant(): Boolean = + with(coefficients) { + var foundAbsoluteTermAndItIsNotZero = false + for ((degs, c) in this) { + if (degs.isNotEmpty()) if (c.isNotZero()) return@with false + else { + if (c.isZero()) return@with false + else foundAbsoluteTermAndItIsNotZero = true + } + } + foundAbsoluteTermAndItIsNotZero + } + + override fun NumberedPolynomial.asConstantOrNull(): C? = + with(coefficients) { + if(isConstant()) getOrElse(emptyList()) { ring.zero } + else null + } + + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedPolynomial.substitute(argument: Map): NumberedPolynomial = this.substitute(ring, argument) + @Suppress("NOTHING_TO_INLINE") + @JvmName("substitutePolynomial") + public inline fun NumberedPolynomial.substitute(argument: Map>): NumberedPolynomial = this.substitute(ring, argument) + + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedPolynomial.asFunction(): (Map) -> NumberedPolynomial = { this.substitute(ring, it) } + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedPolynomial.asFunctionOnConstants(): (Map) -> NumberedPolynomial = { this.substitute(ring, it) } + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedPolynomial.asFunctionOnPolynomials(): (Map>) -> NumberedPolynomial = { this.substitute(ring, it) } + + @Suppress("NOTHING_TO_INLINE") + public inline operator fun NumberedPolynomial.invoke(argument: Map): NumberedPolynomial = this.substitute(ring, argument) + @Suppress("NOTHING_TO_INLINE") + @JvmName("invokePolynomial") + public inline operator fun NumberedPolynomial.invoke(argument: Map>): NumberedPolynomial = this.substitute(ring, argument) + // endregion + + // region Legacy + @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") + override inline fun add(left: NumberedPolynomial, right: NumberedPolynomial): NumberedPolynomial = left + right + @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") + override inline fun multiply(left: NumberedPolynomial, right: NumberedPolynomial): NumberedPolynomial = left * right + // endregion + + // region Utilities + // TODO: Move to region internal utilities with context receiver + internal fun MutableMap, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : MutableMap, C> { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + block() + for ((degs, c) in this) if (c.isZero()) this.remove(degs) + return this + } + internal fun Map, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : Map, C> = + toMutableMap().applyAndRemoveZeros(block) + @OptIn(ExperimentalTypeInference::class) + internal fun buildCoefficients(@BuilderInference builderAction: MutableMap, C>.() -> Unit): Map, C> { + contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } + return buildMap { + builderAction() + for ((degs, c) in this) if (c.isZero()) this.remove(degs) + } + } + // endregion +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 30280a396..99d6b0659 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -5,43 +5,38 @@ package space.kscience.kmath.functions -import space.kscience.kmath.functions.AbstractPolynomialSpace.Companion.optimizedAddMultiplied -import space.kscience.kmath.functions.AbstractPolynomialSpace.Companion.optimizedMultiply import space.kscience.kmath.operations.* import kotlin.jvm.JvmName import kotlin.math.max import kotlin.math.min /** - * Polynomial coefficients model without fixation on specific context they are applied to. + * Polynomial model without fixation on specific context they are applied to. * * @param coefficients constant is the leftmost coefficient. */ public class Polynomial(public val coefficients: List) : AbstractPolynomial { override fun toString(): String = "Polynomial$coefficients" - -// public companion object { -// /** -// * Default name of variables used in string representations. -// * -// * @see Polynomial.toString -// */ -// public var defaultVariableName: String = "x" -// -// /** -// * Represents result of division with remainder. -// */ -// public data class DividingResult( -// val quotient: Polynomial, -// val reminder: Polynomial -// ) -// } } +// region Internal utilities + /** * Represents internal [Polynomial] errors. */ -internal class PolynomialError(message: String): Error(message) +internal class PolynomialError : Error { + constructor(): super() + constructor(message: String): super(message) + constructor(message: String?, cause: Throwable?): super(message, cause) + constructor(cause: Throwable?): super(cause) +} + +/** + * Throws an [PolynomialError] with the given [message]. + */ +internal fun polynomialError(message: Any): Nothing = throw PolynomialError(message.toString()) + +// endregion // region Constructors and converters @@ -66,16 +61,16 @@ public fun T.asPolynomial() : Polynomial = Polynomial(listOf(this)) // endregion /** - * Space of polynomials constructed over ring. + * Space of univariate 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]. */ -@Suppress("INAPPLICABLE_JVM_NAME") // KT-31420 +@Suppress("INAPPLICABLE_JVM_NAME") // TODO: KT-31420 public open class PolynomialSpace>( public val ring: A, -) : AbstractPolynomialSpace>{ +) : AbstractPolynomialSpace> { // region Constant-integer relation @JvmName("constantIntPlus") public override operator fun C.plus(other: Int): C = ring { optimizedAddMultiplied(this@plus, one, other) } @@ -102,8 +97,14 @@ public open class PolynomialSpace>( coefficients .toMutableList() .apply { - if (isEmpty()) this[0] = ring.zero + other - else this[0] = this[0]!! + other + val result = getOrElse(0) { ring.zero } + other + val isResultZero = result.isZero() + + when { + size == 0 && !isResultZero -> add(result) + size > 1 || !isResultZero -> this[0] = result + else -> clear() + } } ) public override operator fun Polynomial.minus(other: Int): Polynomial = @@ -113,8 +114,14 @@ public open class PolynomialSpace>( coefficients .toMutableList() .apply { - if (isEmpty()) this[0] = ring.zero - other - else this[0] = this[0]!! - other + val result = getOrElse(0) { ring.zero } - other + val isResultZero = result.isZero() + + when { + size == 0 && !isResultZero -> add(result) + size > 1 || !isResultZero -> this[0] = result + else -> clear() + } } ) public override operator fun Polynomial.times(other: Int): Polynomial = @@ -134,8 +141,14 @@ public open class PolynomialSpace>( other.coefficients .toMutableList() .apply { - if (isEmpty()) this[0] = ring.zero + this@plus - else this[0] = this[0]!! + this@plus + val result = this@plus + getOrElse(0) { ring.zero } + val isResultZero = result.isZero() + + when { + size == 0 && !isResultZero -> add(result) + size > 1 || !isResultZero -> this[0] = result + else -> clear() + } } ) public override operator fun Int.minus(other: Polynomial): Polynomial = @@ -145,8 +158,16 @@ public open class PolynomialSpace>( other.coefficients .toMutableList() .apply { - if (isEmpty()) this[0] = ring.zero - this@minus - else this[0] = this[0]!! - this@minus + forEachIndexed { index, c -> if (index != 0) this[index] = -c } + + val result = this@minus - getOrElse(0) { ring.zero } + val isResultZero = result.isZero() + + when { + size == 0 && !isResultZero -> add(result) + size > 1 || !isResultZero -> this[0] = result + else -> clear() + } } ) public override operator fun Int.times(other: Polynomial): Polynomial = @@ -183,12 +204,20 @@ public open class PolynomialSpace>( // region Constant-polynomial relation public override operator fun C.plus(other: Polynomial): Polynomial = - with(other.coefficients) { + if (this.isZero()) other + else with(other.coefficients) { if (isEmpty()) Polynomial(listOf(this@plus)) else Polynomial( toMutableList() .apply { - this[0] += this@plus + val result = if (size == 0) this@plus else this@plus + get(0) + val isResultZero = result.isZero() + + when { + size == 0 && !isResultZero -> add(result) + size > 1 || !isResultZero -> this[0] = result + else -> clear() + } } ) } @@ -196,12 +225,22 @@ public open class PolynomialSpace>( // listOf(coefficients[0] + other) + coefficients.subList(1, degree + 1) // ) public override operator fun C.minus(other: Polynomial): Polynomial = - with(other.coefficients) { + if (this.isZero()) other + else with(other.coefficients) { if (isEmpty()) Polynomial(listOf(-this@minus)) else Polynomial( toMutableList() .apply { - this[0] -= this@minus + forEachIndexed { index, c -> if (index != 0) this[index] = -c } + + val result = if (size == 0) this@minus else this@minus - get(0) + val isResultZero = result.isZero() + + when { + size == 0 && !isResultZero -> add(result) + size > 1 || !isResultZero -> this[0] = result + else -> clear() + } } ) } @@ -209,9 +248,10 @@ public open class PolynomialSpace>( // listOf(coefficients[0] + other) + coefficients.subList(1, degree + 1) // ) public override operator fun C.times(other: Polynomial): Polynomial = - Polynomial( + if (this.isZero()) other + else Polynomial( other.coefficients -// .subList(0, other.degree + 1) + .subList(0, other.degree + 1) .map { it * this } ) // endregion @@ -224,7 +264,14 @@ public open class PolynomialSpace>( else Polynomial( toMutableList() .apply { - this[0] += other + val result = if (size == 0) other else get(0) + other + val isResultZero = result.isZero() + + when { + size == 0 && !isResultZero -> add(result) + size > 1 || !isResultZero -> this[0] = result + else -> clear() + } } ) } @@ -232,12 +279,20 @@ public open class PolynomialSpace>( // listOf(coefficients[0] + other) + coefficients.subList(1, degree + 1) // ) public override operator fun Polynomial.minus(other: C): Polynomial = - with(coefficients) { + if (other.isZero()) this + else with(coefficients) { if (isEmpty()) Polynomial(listOf(other)) else Polynomial( toMutableList() .apply { - this[0] -= other + val result = if (size == 0) other else get(0) - other + val isResultZero = result.isZero() + + when { + size == 0 && !isResultZero -> add(result) + size > 1 || !isResultZero -> this[0] = result + else -> clear() + } } ) } @@ -245,9 +300,10 @@ public open class PolynomialSpace>( // listOf(coefficients[0] - other) + coefficients.subList(1, degree + 1) // ) public override operator fun Polynomial.times(other: C): Polynomial = - Polynomial( + if (other.isZero()) this + else Polynomial( coefficients -// .subList(0, degree + 1) + .subList(0, degree + 1) .map { it * other } ) // endregion @@ -283,8 +339,8 @@ public open class PolynomialSpace>( val thisDegree = degree val otherDegree = other.degree return when { - thisDegree == -1 -> this - otherDegree == -1 -> other + thisDegree == -1 -> zero + otherDegree == -1 -> zero else -> Polynomial( (0..(thisDegree + otherDegree)) @@ -293,6 +349,7 @@ public open class PolynomialSpace>( .map { coefficients[it] * other.coefficients[d - it] } .reduce { acc, rational -> acc + rational } } + .run { subList(0, indexOfLast { it.isNotZero() } + 1) } ) } } @@ -321,8 +378,8 @@ public open class PolynomialSpace>( } // endregion - // Not sure is it necessary... // region Polynomial properties + public override val Polynomial.degree: Int get() = coefficients.indexOfLast { it != ring.zero } public override fun Polynomial.asConstantOrNull(): C? = @@ -354,8 +411,8 @@ public open class PolynomialSpace>( public inline operator fun Polynomial.invoke(argument: C): C = this.substitute(ring, argument) @Suppress("NOTHING_TO_INLINE") public inline operator fun Polynomial.invoke(argument: Polynomial): Polynomial = this.substitute(ring, argument) - // endregion + // endregion } /** diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Variable.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Variable.kt new file mode 100644 index 000000000..410604fd3 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Variable.kt @@ -0,0 +1,38 @@ +package space.kscience.kmath.functions + +import kotlin.reflect.KProperty + + +/** + * Represents class of labeled variables like usual + * `x`, `y`, `z`, `a`, `b`, `n`, `m`, etc. + * + * Variables does not contain any information about field (or ring, ets.) they are considered in + * and therefore about coefficient. + * + * @property name Is the label or name of variable. For `x` it is `"x"`, for `n` – `"n"`, etc. + */ +public data class Variable (val name: String) : Comparable { + /** + * Represents the variable as a string. + * + * @return Only name of the variable. + */ + override fun toString(): String = name + /** + * Compares two variables. + * Comparison is realised by comparison of variables' names. + * + * Used in [LabeledPolynomial] and [LabeledRationalFunction] to sort monomials in + * [LabeledPolynomial.toString] and [LabeledRationalFunction.toString] in lexicographic order. + * + * @see Comparable.compareTo + * @sample LabeledPolynomial.monomialComparator + * @return Only name of the variable. + */ + override fun compareTo(other: Variable): Int = name.compareTo(other.name) + + public companion object { + public operator fun getValue(thisRef: Any?, property: KProperty<*>) : Variable = Variable(property.name) + } +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt new file mode 100644 index 000000000..9e5043b8c --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.Group + + +// TODO: All of this should be moved to algebraic structures' place for utilities +// TODO: Move receiver to context receiver +/** + * Multiplication of element and integer. + * + * @receiver the multiplicand. + * @param other the multiplier. + * @return the difference. + */ +internal tailrec fun Group.optimizedMultiply(arg: C, other: Int): C = + when { + other == 0 -> zero + other == 1 -> arg + other == -1 -> -arg + other % 2 == 0 -> optimizedMultiply(arg + arg, other / 2) + other % 2 == 1 -> optimizedAddMultiplied(arg, arg + arg, other / 2) + other % 2 == -1 -> optimizedAddMultiplied(-arg, arg + arg, other / 2) + else -> error("Error in multiplication group instant by integer: got reminder by division by 2 different from 0, 1 and -1") + } + +// TODO: Move receiver to context receiver +/** + * Adds product of [arg] and [multiplier] to [base]. + * + * @receiver the algebra to provide multiplication. + * @param base the augend. + * @param arg the multiplicand. + * @param multiplier the multiplier. + * @return sum of the augend [base] and product of the multiplicand [arg] and the multiplier [multiplier]. + * @author Gleb Minaev + */ +internal tailrec fun Group.optimizedAddMultiplied(base: C, arg: C, multiplier: Int): C = + when { + multiplier == 0 -> base + multiplier == 1 -> base + arg + multiplier == -1 -> base - arg + multiplier % 2 == 0 -> optimizedAddMultiplied(base, arg + arg, multiplier / 2) + multiplier % 2 == 1 -> optimizedAddMultiplied(base + arg, arg + arg, multiplier / 2) + multiplier % 2 == -1 -> optimizedAddMultiplied(base + arg, arg + arg, multiplier / 2) + else -> error("Error in multiplication group instant by integer: got reminder by division by 2 different from 0, 1 and -1") + } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt new file mode 100644 index 000000000..62ac31b64 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt @@ -0,0 +1,490 @@ +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.* +import kotlin.contracts.* + + +// TODO: Docs + +// region Sort of legacy + +//// region Constants +// +//// TODO: Reuse underlying ring extensions +// +//context(LabeledPolynomialSpace) +//@Suppress("NOTHING_TO_INLINE") +//fun > numberConstant(value: Int): C = ring { number(value) } +// +//context(LabeledPolynomialSpace) +//fun > power(arg: C, pow: UInt): C = ring { power(arg, pow) } +// +//context(LabeledPolynomialSpace) +//fun > multiplyWithPower(base: C, arg: C, pow: UInt): C = ring { multiplyWithPower(base, arg, pow) } +// +//// endregion + +//// region Variables +// +//context(LabeledPolynomialSpace) +//fun > power(arg: Variable, pow: UInt): LabeledPolynomial = +// if (pow == 0U) one +// else LabeledPolynomial(mapOf( +// mapOf(arg to pow) to ring.one +// )) +// +//// endregion + +//// region Polynomials +// +//context(LabeledPolynomialSpace) +//fun > number(value: Int): LabeledPolynomial = ring { LabeledPolynomial(mapOf(emptyMap() to number(value))) } +// +//context(LabeledPolynomialSpace) +//fun > multiplyWithPower(base: LabeledPolynomial, arg: LabeledPolynomial, pow: UInt): LabeledPolynomial = +// when { +// arg.isZero() && pow > 0U -> base +// arg.isOne() -> base +// arg.isMinusOne() -> if (pow % 2U == 0U) base else -base +// else -> multiplyWithPowerInternalLogic(base, arg, pow) +// } +// +//// Trivial but slow as duck +//context(LabeledPolynomialSpace) +//internal tailrec fun > multiplyWithPowerInternalLogic(base: LabeledPolynomial, arg: LabeledPolynomial, exponent: UInt): LabeledPolynomial = +// when { +// exponent == 0U -> base +// exponent == 1U -> base * arg +// exponent % 2U == 0U -> multiplyWithPowerInternalLogic(base, arg * arg, exponent / 2U) +// exponent % 2U == 1U -> multiplyWithPowerInternalLogic(base * arg, arg * arg, exponent / 2U) +// else -> error("Error in raising ring instant by unsigned integer: got reminder by division by 2 different from 0 and 1") +// } +// +//// endregion + +// endregion + +// region Utilities + +// TODO: Docs +@OptIn(ExperimentalContracts::class) +public inline fun , R> A.labeledPolynomial(block: LabeledPolynomialSpace.() -> R): R { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return LabeledPolynomialSpace(this).block() +} + +// endregion + +//// region String representations +// +///** +// * Represents the polynomial as a [String] with names of variables substituted with names from [names]. +// * Consider that monomials are sorted in lexicographic order. +// */ +//context(LabeledPolynomialSpace) +//fun > LabeledPolynomial.represent(names: Map = emptyMap()): String = +// coefficients.entries +// .sortedWith { o1, o2 -> LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } +// .asSequence() +// .map { (degs, t) -> +// if (degs.isEmpty()) "$t" +// else { +// when { +// t.isOne() -> "" +// t.isMinusOne() -> "-" +// else -> "$t " +// } + +// degs +// .toSortedMap() +// .filter { it.value > 0U } +// .map { (variable, deg) -> +// val variableName = names.getOrDefault(variable, variable.toString()) +// when (deg) { +// 1U -> variableName +// else -> "$variableName^$deg" +// } +// } +// .joinToString(separator = " ") { it } +// } +// } +// .joinToString(separator = " + ") { it } +// .ifEmpty { "0" } +// +///** +// * Represents the polynomial as a [String] naming variables by [namer]. +// * Consider that monomials are sorted in lexicographic order. +// */ +//context(LabeledPolynomialSpace) +//fun > LabeledPolynomial.represent(namer: (Variable) -> String): String = +// coefficients.entries +// .sortedWith { o1, o2 -> LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } +// .asSequence() +// .map { (degs, t) -> +// if (degs.isEmpty()) "$t" +// else { +// when { +// t.isOne() -> "" +// t.isMinusOne() -> "-" +// else -> "$t " +// } + +// degs +// .toSortedMap() +// .filter { it.value > 0U } +// .map { (variable, deg) -> +// when (deg) { +// 1U -> namer(variable) +// else -> "${namer(variable)}^$deg" +// } +// } +// .joinToString(separator = " ") { it } +// } +// } +// .joinToString(separator = " + ") { it } +// .ifEmpty { "0" } +// +///** +// * Represents the polynomial as a [String] with names of variables substituted with names from [names] and with +// * brackets around the string if needed (i.e. when there are at least two addends in the representation). +// * Consider that monomials are sorted in lexicographic order. +// */ +//context(LabeledPolynomialSpace) +//fun > LabeledPolynomial.representWithBrackets(names: Map = emptyMap()): String = +// with(represent(names)) { if (coefficients.count() == 1) this else "($this)" } +// +///** +// * Represents the polynomial as a [String] naming variables by [namer] and with brackets around the string if needed +// * (i.e. when there are at least two addends in the representation). +// * Consider that monomials are sorted in lexicographic order. +// */ +//context(LabeledPolynomialSpace) +//fun > LabeledPolynomial.representWithBrackets(namer: (Variable) -> String): String = +// with(represent(namer)) { if (coefficients.count() == 1) this else "($this)" } +// +///** +// * Represents the polynomial as a [String] with names of variables substituted with names from [names]. +// * Consider that monomials are sorted in **reversed** lexicographic order. +// */ +//context(LabeledPolynomialSpace) +//fun > LabeledPolynomial.representReversed(names: Map = emptyMap()): String = +// coefficients.entries +// .sortedWith { o1, o2 -> -LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } +// .asSequence() +// .map { (degs, t) -> +// if (degs.isEmpty()) "$t" +// else { +// when { +// t.isOne() -> "" +// t.isMinusOne() -> "-" +// else -> "$t " +// } + +// degs +// .toSortedMap() +// .filter { it.value > 0U } +// .map { (variable, deg) -> +// val variableName = names.getOrDefault(variable, variable.toString()) +// when (deg) { +// 1U -> variableName +// else -> "$variableName^$deg" +// } +// } +// .joinToString(separator = " ") { it } +// } +// } +// .joinToString(separator = " + ") { it } +// .ifEmpty { "0" } +// +///** +// * Represents the polynomial as a [String] naming variables by [namer]. +// * Consider that monomials are sorted in **reversed** lexicographic order. +// */ +//context(LabeledPolynomialSpace) +//fun > LabeledPolynomial.representReversed(namer: (Variable) -> String): String = +// coefficients.entries +// .sortedWith { o1, o2 -> -LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } +// .asSequence() +// .map { (degs, t) -> +// if (degs.isEmpty()) "$t" +// else { +// when { +// t.isOne() -> "" +// t.isMinusOne() -> "-" +// else -> "$t " +// } + +// degs +// .toSortedMap() +// .filter { it.value > 0U } +// .map { (variable, deg) -> +// when (deg) { +// 1U -> namer(variable) +// else -> "${namer(variable)}^$deg" +// } +// } +// .joinToString(separator = " ") { it } +// } +// } +// .joinToString(separator = " + ") { it } +// .ifEmpty { "0" } +// +///** +// * Represents the polynomial as a [String] with names of variables substituted with names from [names] and with +// * brackets around the string if needed (i.e. when there are at least two addends in the representation). +// * Consider that monomials are sorted in **reversed** lexicographic order. +// */ +//context(LabeledPolynomialSpace) +//fun > LabeledPolynomial.representReversedWithBrackets(names: Map = emptyMap()): String = +// with(representReversed(names)) { if (coefficients.count() == 1) this else "($this)" } +// +///** +// * Represents the polynomial as a [String] naming variables by [namer] and with brackets around the string if needed +// * (i.e. when there are at least two addends in the representation). +// * Consider that monomials are sorted in **reversed** lexicographic order. +// */ +//context(LabeledPolynomialSpace) +//fun > LabeledPolynomial.representReversedWithBrackets(namer: (Variable) -> String): String = +// with(representReversed(namer)) { if (coefficients.count() == 1) this else "($this)" } +// +//// endregion + +// region Operator extensions + +//// region Field case +// +//operator fun > Polynomial.div(other: Polynomial): Polynomial { +// if (other.isZero()) throw ArithmeticException("/ by zero") +// if (isZero()) return this +// +// fun Map, T>.leadingTerm() = +// this +// .asSequence() +// .map { Pair(it.key, it.value) } +// .reduce { (accDegs, accC), (listDegs, listC) -> +// for (i in 0..accDegs.lastIndex) { +// if (accDegs[i] > listDegs.getOrElse(i) { 0 }) return@reduce accDegs to accC +// if (accDegs[i] < listDegs.getOrElse(i) { 0 }) return@reduce listDegs to listC +// } +// if (accDegs.size < listDegs.size) listDegs to listC else accDegs to accC +// } +// +// var thisCoefficients = coefficients.toMutableMap() +// val otherCoefficients = other.coefficients +// val quotientCoefficients = HashMap, T>() +// +// var (thisLeadingTermDegs, thisLeadingTermC) = thisCoefficients.leadingTerm() +// val (otherLeadingTermDegs, otherLeadingTermC) = otherCoefficients.leadingTerm() +// +// while ( +// thisLeadingTermDegs.size >= otherLeadingTermDegs.size && +// (0..otherLeadingTermDegs.lastIndex).all { thisLeadingTermDegs[it] >= otherLeadingTermDegs[it] } +// ) { +// val multiplierDegs = +// thisLeadingTermDegs +// .mapIndexed { index, deg -> deg - otherLeadingTermDegs.getOrElse(index) { 0 } } +// .cleanUp() +// val multiplierC = thisLeadingTermC / otherLeadingTermC +// +// quotientCoefficients[multiplierDegs] = multiplierC +// +// for ((degs, t) in otherCoefficients) { +// val productDegs = +// (0..max(degs.lastIndex, multiplierDegs.lastIndex)) +// .map { degs.getOrElse(it) { 0 } + multiplierDegs.getOrElse(it) { 0 } } +// .cleanUp() +// val productC = t * multiplierC +// thisCoefficients[productDegs] = +// if (productDegs in thisCoefficients) thisCoefficients[productDegs]!! - productC else -productC +// } +// +// thisCoefficients = thisCoefficients.filterValues { it.isNotZero() }.toMutableMap() +// +// if (thisCoefficients.isEmpty()) +// return Polynomial(quotientCoefficients, toCheckInput = false) +// +// val t = thisCoefficients.leadingTerm() +// thisLeadingTermDegs = t.first +// thisLeadingTermC = t.second +// } +// +// return Polynomial(quotientCoefficients, toCheckInput = false) +//} +// +//operator fun > Polynomial.div(other: T): Polynomial = +// if (other.isZero()) throw ArithmeticException("/ by zero") +// else +// Polynomial( +// coefficients +// .mapValues { it.value / other }, +// toCheckInput = false +// ) +// +//operator fun > Polynomial.rem(other: Polynomial): Polynomial { +// if (other.isZero()) throw ArithmeticException("/ by zero") +// if (isZero()) return this +// +// fun Map, T>.leadingTerm() = +// this +// .asSequence() +// .map { Pair(it.key, it.value) } +// .reduce { (accDegs, accC), (listDegs, listC) -> +// for (i in 0..accDegs.lastIndex) { +// if (accDegs[i] > listDegs.getOrElse(i) { 0 }) return@reduce accDegs to accC +// if (accDegs[i] < listDegs.getOrElse(i) { 0 }) return@reduce listDegs to listC +// } +// if (accDegs.size < listDegs.size) listDegs to listC else accDegs to accC +// } +// +// var thisCoefficients = coefficients.toMutableMap() +// val otherCoefficients = other.coefficients +// +// var (thisLeadingTermDegs, thisLeadingTermC) = thisCoefficients.leadingTerm() +// val (otherLeadingTermDegs, otherLeadingTermC) = otherCoefficients.leadingTerm() +// +// while ( +// thisLeadingTermDegs.size >= otherLeadingTermDegs.size && +// (0..otherLeadingTermDegs.lastIndex).all { thisLeadingTermDegs[it] >= otherLeadingTermDegs[it] } +// ) { +// val multiplierDegs = +// thisLeadingTermDegs +// .mapIndexed { index, deg -> deg - otherLeadingTermDegs.getOrElse(index) { 0 } } +// .cleanUp() +// val multiplierC = thisLeadingTermC / otherLeadingTermC +// +// for ((degs, t) in otherCoefficients) { +// val productDegs = +// (0..max(degs.lastIndex, multiplierDegs.lastIndex)) +// .map { degs.getOrElse(it) { 0 } + multiplierDegs.getOrElse(it) { 0 } } +// .cleanUp() +// val productC = t * multiplierC +// thisCoefficients[productDegs] = +// if (productDegs in thisCoefficients) thisCoefficients[productDegs]!! - productC else -productC +// } +// +// thisCoefficients = thisCoefficients.filterValues { it.isNotZero() }.toMutableMap() +// +// if (thisCoefficients.isEmpty()) +// return Polynomial(thisCoefficients, toCheckInput = false) +// +// val t = thisCoefficients.leadingTerm() +// thisLeadingTermDegs = t.first +// thisLeadingTermC = t.second +// } +// +// return Polynomial(thisCoefficients, toCheckInput = false) +//} +// +//infix fun > Polynomial.divrem(other: Polynomial): Polynomial.Companion.DividingResult { +// if (other.isZero()) throw ArithmeticException("/ by zero") +// if (isZero()) return Polynomial.Companion.DividingResult(this, this) +// +// fun Map, T>.leadingTerm() = +// this +// .asSequence() +// .map { Pair(it.key, it.value) } +// .reduce { (accDegs, accC), (listDegs, listC) -> +// for (i in 0..accDegs.lastIndex) { +// if (accDegs[i] > listDegs.getOrElse(i) { 0 }) return@reduce accDegs to accC +// if (accDegs[i] < listDegs.getOrElse(i) { 0 }) return@reduce listDegs to listC +// } +// if (accDegs.size < listDegs.size) listDegs to listC else accDegs to accC +// } +// +// var thisCoefficients = coefficients.toMutableMap() +// val otherCoefficients = other.coefficients +// val quotientCoefficients = HashMap, T>() +// +// var (thisLeadingTermDegs, thisLeadingTermC) = thisCoefficients.leadingTerm() +// val (otherLeadingTermDegs, otherLeadingTermC) = otherCoefficients.leadingTerm() +// +// while ( +// thisLeadingTermDegs.size >= otherLeadingTermDegs.size && +// (0..otherLeadingTermDegs.lastIndex).all { thisLeadingTermDegs[it] >= otherLeadingTermDegs[it] } +// ) { +// val multiplierDegs = +// thisLeadingTermDegs +// .mapIndexed { index, deg -> deg - otherLeadingTermDegs.getOrElse(index) { 0 } } +// .cleanUp() +// val multiplierC = thisLeadingTermC / otherLeadingTermC +// +// quotientCoefficients[multiplierDegs] = multiplierC +// +// for ((degs, t) in otherCoefficients) { +// val productDegs = +// (0..max(degs.lastIndex, multiplierDegs.lastIndex)) +// .map { degs.getOrElse(it) { 0 } + multiplierDegs.getOrElse(it) { 0 } } +// .cleanUp() +// val productC = t * multiplierC +// thisCoefficients[productDegs] = +// if (productDegs in thisCoefficients) thisCoefficients[productDegs]!! - productC else -productC +// } +// +// thisCoefficients = thisCoefficients.filterValues { it.isNotZero() }.toMutableMap() +// +// if (thisCoefficients.isEmpty()) +// return Polynomial.Companion.DividingResult( +// Polynomial(quotientCoefficients, toCheckInput = false), +// Polynomial(thisCoefficients, toCheckInput = false) +// ) +// +// val t = thisCoefficients.leadingTerm() +// thisLeadingTermDegs = t.first +// thisLeadingTermC = t.second +// } +// +// return Polynomial.Companion.DividingResult( +// Polynomial(quotientCoefficients, toCheckInput = false), +// Polynomial(thisCoefficients, toCheckInput = false) +// ) +//} +// +//// endregion + +// endregion + +//// region Polynomial substitution and functional representation +// +//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 = degs.entries.asSequence().filter { it.key in args }.fold(c) { acc, (variable, deg) -> +// multiplyWithPower(acc, args[variable]!!, deg) +// } +// this[newDegs] = if (newDegs in this) this[newDegs]!! + newC else newC +// } +// } +// ) +//} +// +//// TODO: Replace with optimisation: the [result] may be unboxed, and all operations may be performed as soon as +//// possible on it +//@JvmName("substitutePolynomial") +//fun LabeledPolynomial.substitute(ring: Ring, arg: Map>) : LabeledPolynomial = +// ring.labeledPolynomial { +// if (coefficients.isEmpty()) return zero +// coefficients +// .asSequence() +// .map { (degs, c) -> +// degs.entries +// .asSequence() +// .filter { it.key in arg } +// .fold(LabeledPolynomial(mapOf(degs.filterKeys { it !in arg } to c))) { acc, (index, deg) -> +// multiplyWithPower(acc, arg[index]!!, deg) +// } +// } +// .reduce { acc, polynomial -> acc + polynomial } // TODO: Rewrite. Might be slow. +// } +// +//// TODO: Substitute rational function +// +//fun > LabeledPolynomial.asFunctionOver(ring: A): (Map) -> LabeledPolynomial = +// { substitute(ring, it) } +// +//fun > LabeledPolynomial.asPolynomialFunctionOver(ring: A): (Map>) -> LabeledPolynomial = +// { substitute(ring, it) } +// +//// endregion + +//// region Algebraic derivative and antiderivative +//// TODO +//// endregion \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt new file mode 100644 index 000000000..d4053442d --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt @@ -0,0 +1,605 @@ +package space.kscience.kmath.functions + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.* +import kotlin.contracts.* +import kotlin.jvm.JvmName + + +// TODO: Docs + +// region Sort of legacy + +//// region Constants +// +//// TODO: Reuse underlying ring extensions +// +//context(NumberedPolynomialSpace) +//@Suppress("NOTHING_TO_INLINE") +//public fun > numberConstant(value: Int): C = ring { number(value) } +// +//context(NumberedPolynomialSpace) +//public fun > multiplyWithPower(base: C, arg: C, pow: UInt): C = ring { multiplyWithPower(base, arg, pow) } +// +//// endregion + +//// region Polynomials +// +//context(NumberedPolynomialSpace) +//public fun > number(value: Int): NumberedPolynomial = ring { NumberedPolynomial(mapOf(emptyList() to number(value))) } +// +//context(NumberedPolynomialSpace) +//public fun > multiplyWithPower(base: NumberedPolynomial, arg: NumberedPolynomial, pow: UInt): NumberedPolynomial = +// when { +// arg.isZero() && pow > 0U -> base +// arg.isOne() -> base +// arg.isMinusOne() -> if (pow % 2U == 0U) base else -base +// else -> multiplyWithPowerInternalLogic(base, arg, pow) +// } +// +//// Trivial but slow as duck +//context(NumberedPolynomialSpace) +//internal tailrec fun > multiplyWithPowerInternalLogic(base: NumberedPolynomial, arg: NumberedPolynomial, exponent: UInt): NumberedPolynomial = +// when { +// exponent == 0U -> base +// exponent == 1U -> base * arg +// exponent % 2U == 0U -> multiplyWithPowerInternalLogic(base, arg * arg, exponent / 2U) +// exponent % 2U == 1U -> multiplyWithPowerInternalLogic(base * arg, arg * arg, exponent / 2U) +// else -> error("Error in raising ring instant by unsigned integer: got reminder by division by 2 different from 0 and 1") +// } +// +//// endregion + +// endregion + +// region Utilities + +// TODO: Docs +@OptIn(ExperimentalContracts::class) +public inline fun , R> A.numberedPolynomial(block: NumberedPolynomialSpace.() -> R): R { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return NumberedPolynomialSpace(this).block() +} + +// endregion + +//// region String representations +// +///** +// * Represents the polynomial as a [String] where name of variable with index `i` is [withVariableName] + `"_${i+1}"`. +// * Consider that monomials are sorted in lexicographic order. +// */ +//context(NumberedPolynomialSpace) +//public fun > NumberedPolynomial.represent(withVariableName: String = NumberedPolynomial.defaultVariableName): String = +// coefficients.entries +// .sortedWith { o1, o2 -> NumberedPolynomial.monomialComparator.compare(o1.key, o2.key) } +// .asSequence() +// .map { (degs, t) -> +// if (degs.isEmpty()) "$t" +// else { +// when { +// t.isOne() -> "" +// t.isMinusOne() -> "-" +// else -> "$t " +// } + +// degs +// .mapIndexed { index, deg -> +// when (deg) { +// 0U -> "" +// 1U -> "${withVariableName}_${index+1}" +// else -> "${withVariableName}_${index+1}^$deg" +// } +// } +// .filter { it.isNotEmpty() } +// .joinToString(separator = " ") { it } +// } +// } +// .joinToString(separator = " + ") { it } +// .ifEmpty { "0" } +// +///** +// * Represents the polynomial as a [String] naming variables by [namer]. +// * Consider that monomials are sorted in lexicographic order. +// */ +//context(NumberedPolynomialSpace) +//public fun > NumberedPolynomial.represent(namer: (Int) -> String): String = +// coefficients.entries +// .sortedWith { o1, o2 -> NumberedPolynomial.monomialComparator.compare(o1.key, o2.key) } +// .asSequence() +// .map { (degs, t) -> +// if (degs.isEmpty()) "$t" +// else { +// when { +// t.isOne() -> "" +// t.isMinusOne() -> "-" +// else -> "$t " +// } + +// degs +// .mapIndexed { index, deg -> +// when (deg) { +// 0U -> "" +// 1U -> namer(index) +// else -> "${namer(index)}^$deg" +// } +// } +// .filter { it.isNotEmpty() } +// .joinToString(separator = " ") { it } +// } +// } +// .joinToString(separator = " + ") { it } +// .ifEmpty { "0" } +// +///** +// * Represents the polynomial as a [String] where name of variable with index `i` is [withVariableName] + `"_${i+1}"` +// * and with brackets around the string if needed (i.e. when there are at least two addends in the representation). +// * Consider that monomials are sorted in lexicographic order. +// */ +//context(NumberedPolynomialSpace) +//public fun > NumberedPolynomial.representWithBrackets(withVariableName: String = NumberedPolynomial.defaultVariableName): String = +// with(represent(withVariableName)) { if (coefficients.count() == 1) this else "($this)" } +// +///** +// * Represents the polynomial as a [String] naming variables by [namer] and with brackets around the string if needed +// * (i.e. when there are at least two addends in the representation). +// * Consider that monomials are sorted in lexicographic order. +// */ +//context(NumberedPolynomialSpace) +//public fun > NumberedPolynomial.representWithBrackets(namer: (Int) -> String): String = +// with(represent(namer)) { if (coefficients.count() == 1) this else "($this)" } +// +///** +// * Represents the polynomial as a [String] where name of variable with index `i` is [withVariableName] + `"_${i+1}"`. +// * Consider that monomials are sorted in **reversed** lexicographic order. +// */ +//context(NumberedPolynomialSpace) +//public fun > NumberedPolynomial.representReversed(withVariableName: String = NumberedPolynomial.defaultVariableName): String = +// coefficients.entries +// .sortedWith { o1, o2 -> -NumberedPolynomial.monomialComparator.compare(o1.key, o2.key) } +// .asSequence() +// .map { (degs, t) -> +// if (degs.isEmpty()) "$t" +// else { +// when { +// t.isOne() -> "" +// t.isMinusOne() -> "-" +// else -> "$t " +// } + +// degs +// .mapIndexed { index, deg -> +// when (deg) { +// 0U -> "" +// 1U -> "${withVariableName}_${index+1}" +// else -> "${withVariableName}_${index+1}^$deg" +// } +// } +// .filter { it.isNotEmpty() } +// .joinToString(separator = " ") { it } +// } +// } +// .joinToString(separator = " + ") { it } +// .ifEmpty { "0" } +// +///** +// * Represents the polynomial as a [String] naming variables by [namer]. +// * Consider that monomials are sorted in **reversed** lexicographic order. +// */ +//context(NumberedPolynomialSpace) +//public fun > NumberedPolynomial.representReversed(namer: (Int) -> String): String = +// coefficients.entries +// .sortedWith { o1, o2 -> -NumberedPolynomial.monomialComparator.compare(o1.key, o2.key) } +// .asSequence() +// .map { (degs, t) -> +// if (degs.isEmpty()) "$t" +// else { +// when { +// t.isOne() -> "" +// t.isMinusOne() -> "-" +// else -> "$t " +// } + +// degs +// .mapIndexed { index, deg -> +// when (deg) { +// 0U -> "" +// 1U -> namer(index) +// else -> "${namer(index)}^$deg" +// } +// } +// .filter { it.isNotEmpty() } +// .joinToString(separator = " ") { it } +// } +// } +// .joinToString(separator = " + ") { it } +// .ifEmpty { "0" } +// +///** +// * Represents the polynomial as a [String] where name of variable with index `i` is [withVariableName] + `"_${i+1}"` +// * and with brackets around the string if needed (i.e. when there are at least two addends in the representation). +// * Consider that monomials are sorted in **reversed** lexicographic order. +// */ +//context(NumberedPolynomialSpace) +//public fun > NumberedPolynomial.representReversedWithBrackets(withVariableName: String = NumberedPolynomial.defaultVariableName): String = +// with(representReversed(withVariableName)) { if (coefficients.count() == 1) this else "($this)" } +// +///** +// * Represents the polynomial as a [String] naming variables by [namer] and with brackets around the string if needed +// * (i.e. when there are at least two addends in the representation). +// * Consider that monomials are sorted in **reversed** lexicographic order. +// */ +//context(NumberedPolynomialSpace) +//public fun > NumberedPolynomial.representReversedWithBrackets(namer: (Int) -> String): String = +// with(representReversed(namer)) { if (coefficients.count() == 1) this else "($this)" } +// +//// endregion + +//// region Polynomial substitution and functional representation +// +//public fun NumberedPolynomial.substitute(ring: Ring, args: Map): NumberedPolynomial = ring { +// if (coefficients.isEmpty()) return this@substitute +// NumberedPolynomial( +// buildMap { +// coefficients.forEach { (degs, c) -> +// val newDegs = degs.mapIndexed { index, deg -> if (index in args) 0U else deg }.cleanUp() +// val newC = degs.foldIndexed(c) { index, acc, deg -> +// if (index in args) multiplyWithPower(acc, args[index]!!, deg) +// else acc +// } +// this[newDegs] = if (newDegs in this) this[newDegs]!! + newC else newC +// } +// } +// ) +//} +// +//// TODO: Replace with optimisation: the [result] may be unboxed, and all operations may be performed as soon as +//// possible on it +//@JvmName("substitutePolynomial") +//public fun NumberedPolynomial.substitute(ring: Ring, arg: Map>) : NumberedPolynomial = +// ring.numberedPolynomialSpace { +// if (coefficients.isEmpty()) return zero +// coefficients +// .asSequence() +// .map { (degs, c) -> +// degs.foldIndexed( +// NumberedPolynomial( +// degs.mapIndexed { index, deg -> if (index in arg) 0U else deg } to c +// ) +// ) { index, acc, deg -> if (index in arg) multiplyWithPower(acc, arg[index]!!, deg) else acc } +// } +// .reduce { acc, polynomial -> acc + polynomial } // TODO: Rewrite. Might be slow. +// } +// +//// TODO: Substitute rational function +// +//public fun > NumberedPolynomial.asFunctionOver(ring: A): (Map) -> NumberedPolynomial = +// { substitute(ring, it) } +// +//public fun > NumberedPolynomial.asPolynomialFunctionOver(ring: A): (Map>) -> NumberedPolynomial = +// { substitute(ring, it) } +// +//// endregion + +// region Operator extensions + +//// region Field case +// +//operator fun > Polynomial.div(other: Polynomial): Polynomial { +// if (other.isZero()) throw ArithmeticException("/ by zero") +// if (isZero()) return this +// +// fun Map, T>.leadingTerm() = +// this +// .asSequence() +// .map { Pair(it.key, it.value) } +// .reduce { (accDegs, accC), (listDegs, listC) -> +// for (i in 0..accDegs.lastIndex) { +// if (accDegs[i] > listDegs.getOrElse(i) { 0 }) return@reduce accDegs to accC +// if (accDegs[i] < listDegs.getOrElse(i) { 0 }) return@reduce listDegs to listC +// } +// if (accDegs.size < listDegs.size) listDegs to listC else accDegs to accC +// } +// +// var thisCoefficients = coefficients.toMutableMap() +// val otherCoefficients = other.coefficients +// val quotientCoefficients = HashMap, T>() +// +// var (thisLeadingTermDegs, thisLeadingTermC) = thisCoefficients.leadingTerm() +// val (otherLeadingTermDegs, otherLeadingTermC) = otherCoefficients.leadingTerm() +// +// while ( +// thisLeadingTermDegs.size >= otherLeadingTermDegs.size && +// (0..otherLeadingTermDegs.lastIndex).all { thisLeadingTermDegs[it] >= otherLeadingTermDegs[it] } +// ) { +// val multiplierDegs = +// thisLeadingTermDegs +// .mapIndexed { index, deg -> deg - otherLeadingTermDegs.getOrElse(index) { 0 } } +// .cleanUp() +// val multiplierC = thisLeadingTermC / otherLeadingTermC +// +// quotientCoefficients[multiplierDegs] = multiplierC +// +// for ((degs, t) in otherCoefficients) { +// val productDegs = +// (0..max(degs.lastIndex, multiplierDegs.lastIndex)) +// .map { degs.getOrElse(it) { 0 } + multiplierDegs.getOrElse(it) { 0 } } +// .cleanUp() +// val productC = t * multiplierC +// thisCoefficients[productDegs] = +// if (productDegs in thisCoefficients) thisCoefficients[productDegs]!! - productC else -productC +// } +// +// thisCoefficients = thisCoefficients.filterValues { it.isNotZero() }.toMutableMap() +// +// if (thisCoefficients.isEmpty()) +// return Polynomial(quotientCoefficients, toCheckInput = false) +// +// val t = thisCoefficients.leadingTerm() +// thisLeadingTermDegs = t.first +// thisLeadingTermC = t.second +// } +// +// return Polynomial(quotientCoefficients, toCheckInput = false) +//} +// +//operator fun > Polynomial.div(other: T): Polynomial = +// if (other.isZero()) throw ArithmeticException("/ by zero") +// else +// Polynomial( +// coefficients +// .mapValues { it.value / other }, +// toCheckInput = false +// ) +// +//operator fun > Polynomial.rem(other: Polynomial): Polynomial { +// if (other.isZero()) throw ArithmeticException("/ by zero") +// if (isZero()) return this +// +// fun Map, T>.leadingTerm() = +// this +// .asSequence() +// .map { Pair(it.key, it.value) } +// .reduce { (accDegs, accC), (listDegs, listC) -> +// for (i in 0..accDegs.lastIndex) { +// if (accDegs[i] > listDegs.getOrElse(i) { 0 }) return@reduce accDegs to accC +// if (accDegs[i] < listDegs.getOrElse(i) { 0 }) return@reduce listDegs to listC +// } +// if (accDegs.size < listDegs.size) listDegs to listC else accDegs to accC +// } +// +// var thisCoefficients = coefficients.toMutableMap() +// val otherCoefficients = other.coefficients +// +// var (thisLeadingTermDegs, thisLeadingTermC) = thisCoefficients.leadingTerm() +// val (otherLeadingTermDegs, otherLeadingTermC) = otherCoefficients.leadingTerm() +// +// while ( +// thisLeadingTermDegs.size >= otherLeadingTermDegs.size && +// (0..otherLeadingTermDegs.lastIndex).all { thisLeadingTermDegs[it] >= otherLeadingTermDegs[it] } +// ) { +// val multiplierDegs = +// thisLeadingTermDegs +// .mapIndexed { index, deg -> deg - otherLeadingTermDegs.getOrElse(index) { 0 } } +// .cleanUp() +// val multiplierC = thisLeadingTermC / otherLeadingTermC +// +// for ((degs, t) in otherCoefficients) { +// val productDegs = +// (0..max(degs.lastIndex, multiplierDegs.lastIndex)) +// .map { degs.getOrElse(it) { 0 } + multiplierDegs.getOrElse(it) { 0 } } +// .cleanUp() +// val productC = t * multiplierC +// thisCoefficients[productDegs] = +// if (productDegs in thisCoefficients) thisCoefficients[productDegs]!! - productC else -productC +// } +// +// thisCoefficients = thisCoefficients.filterValues { it.isNotZero() }.toMutableMap() +// +// if (thisCoefficients.isEmpty()) +// return Polynomial(thisCoefficients, toCheckInput = false) +// +// val t = thisCoefficients.leadingTerm() +// thisLeadingTermDegs = t.first +// thisLeadingTermC = t.second +// } +// +// return Polynomial(thisCoefficients, toCheckInput = false) +//} +// +//infix fun > Polynomial.divrem(other: Polynomial): Polynomial.Companion.DividingResult { +// if (other.isZero()) throw ArithmeticException("/ by zero") +// if (isZero()) return Polynomial.Companion.DividingResult(this, this) +// +// fun Map, T>.leadingTerm() = +// this +// .asSequence() +// .map { Pair(it.key, it.value) } +// .reduce { (accDegs, accC), (listDegs, listC) -> +// for (i in 0..accDegs.lastIndex) { +// if (accDegs[i] > listDegs.getOrElse(i) { 0 }) return@reduce accDegs to accC +// if (accDegs[i] < listDegs.getOrElse(i) { 0 }) return@reduce listDegs to listC +// } +// if (accDegs.size < listDegs.size) listDegs to listC else accDegs to accC +// } +// +// var thisCoefficients = coefficients.toMutableMap() +// val otherCoefficients = other.coefficients +// val quotientCoefficients = HashMap, T>() +// +// var (thisLeadingTermDegs, thisLeadingTermC) = thisCoefficients.leadingTerm() +// val (otherLeadingTermDegs, otherLeadingTermC) = otherCoefficients.leadingTerm() +// +// while ( +// thisLeadingTermDegs.size >= otherLeadingTermDegs.size && +// (0..otherLeadingTermDegs.lastIndex).all { thisLeadingTermDegs[it] >= otherLeadingTermDegs[it] } +// ) { +// val multiplierDegs = +// thisLeadingTermDegs +// .mapIndexed { index, deg -> deg - otherLeadingTermDegs.getOrElse(index) { 0 } } +// .cleanUp() +// val multiplierC = thisLeadingTermC / otherLeadingTermC +// +// quotientCoefficients[multiplierDegs] = multiplierC +// +// for ((degs, t) in otherCoefficients) { +// val productDegs = +// (0..max(degs.lastIndex, multiplierDegs.lastIndex)) +// .map { degs.getOrElse(it) { 0 } + multiplierDegs.getOrElse(it) { 0 } } +// .cleanUp() +// val productC = t * multiplierC +// thisCoefficients[productDegs] = +// if (productDegs in thisCoefficients) thisCoefficients[productDegs]!! - productC else -productC +// } +// +// thisCoefficients = thisCoefficients.filterValues { it.isNotZero() }.toMutableMap() +// +// if (thisCoefficients.isEmpty()) +// return Polynomial.Companion.DividingResult( +// Polynomial(quotientCoefficients, toCheckInput = false), +// Polynomial(thisCoefficients, toCheckInput = false) +// ) +// +// val t = thisCoefficients.leadingTerm() +// thisLeadingTermDegs = t.first +// thisLeadingTermC = t.second +// } +// +// return Polynomial.Companion.DividingResult( +// Polynomial(quotientCoefficients, toCheckInput = false), +// Polynomial(thisCoefficients, toCheckInput = false) +// ) +//} +// +//// endregion + +// endregion + +// region Polynomial substitution and functional representation + +// TODO: May be apply Horner's method too? +/** + * Evaluates the value of the given double polynomial for given double argument. + */ +public fun NumberedPolynomial.substitute(args: Map): NumberedPolynomial = Double.algebra { + val acc = LinkedHashMap, Double>(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, substitutor) -> + val deg = degs.getOrElse(variable) { 0u } + if (deg == 0u) product else product * substitutor.pow(deg.toInt()) + } + if (newDegs !in acc) acc[newDegs] = c + else acc[newDegs] = acc[newDegs]!! + c + } + return NumberedPolynomial(acc) +} + +/** + * Evaluates the value of the given polynomial for given argument. + * + * It is an implementation of [Horner's method](https://en.wikipedia.org/wiki/Horner%27s_method). + */ +public fun NumberedPolynomial.substitute(ring: Ring, args: Map): NumberedPolynomial = ring { + val acc = LinkedHashMap, C>(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, substitutor) -> + val deg = degs.getOrElse(variable) { 0u } + if (deg == 0u) product else product * power(substitutor, deg) + } + if (newDegs !in acc) acc[newDegs] = c + else acc[newDegs] = acc[newDegs]!! + c + } + return NumberedPolynomial(acc) +} + +// TODO: (Waiting for hero) Replace with optimisation: the [result] may be unboxed, and all operations may be performed +// as soon as possible on it +@JvmName("substitutePolynomial") +public fun NumberedPolynomial.substitute(ring: Ring, args: Map>) : NumberedPolynomial = TODO() /*ring.numberedPolynomial { + val acc = LinkedHashMap, NumberedPolynomial>(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.asNumberedPolynomial()) { product, (variable, substitutor) -> + val deg = degs.getOrElse(variable) { 0u } + if (deg == 0u) product else product * power(substitutor, deg) + } + if (newDegs !in acc) acc[newDegs] = c.asNumberedPolynomial() + else acc[newDegs] = acc[newDegs]!! + c + } +}*/ + +/** + * Represent the polynomial as a regular context-less function. + */ +public fun > NumberedPolynomial.asFunction(ring: A): (Map) -> NumberedPolynomial = { substitute(ring, it) } + +/** + * Represent the polynomial as a regular context-less function. + */ +public fun > NumberedPolynomial.asPolynomialFunctionOver(ring: A): (Map>) -> NumberedPolynomial = { substitute(ring, it) } + +// endregion + +// region Algebraic derivative and antiderivative + +/** + * Returns algebraic derivative of received polynomial. + */ +@UnstableKMathAPI +public fun NumberedPolynomial.derivativeBy( + algebra: A, + variable: Int, +): Polynomial where A : Ring, A : NumericAlgebra = algebra { + TODO() +} + +/** + * Returns algebraic derivative of received polynomial. + */ +@UnstableKMathAPI +public fun NumberedPolynomial.derivativeBy( + algebra: A, + variables: IntArray, +): Polynomial where A : Ring, A : NumericAlgebra = algebra { + TODO() +} + +/** + * Returns algebraic derivative of received polynomial. + */ +@UnstableKMathAPI +public fun NumberedPolynomial.derivativeBy( + algebra: A, + variables: Collection, +): Polynomial where A : Ring, A : NumericAlgebra = derivativeBy(algebra, variables.toIntArray()) + +/** + * Create a polynomial witch represents indefinite integral version of this polynomial + */ +@UnstableKMathAPI +public fun NumberedPolynomial.antiderivativeBy( + algebra: A, + variable: Int, +): Polynomial where A : Field, A : NumericAlgebra = algebra { + TODO() +} + +/** + * Create a polynomial witch represents indefinite integral version of this polynomial + */ +@UnstableKMathAPI +public fun NumberedPolynomial.antiderivativeBy( + algebra: A, + variables: IntArray, +): Polynomial where A : Field, A : NumericAlgebra = algebra { + TODO() +} + +/** + * Create a polynomial witch represents indefinite integral version of this polynomial + */ +@UnstableKMathAPI +public fun NumberedPolynomial.antiderivativeBy( + algebra: A, + variables: Collection, +): Polynomial where A : Field, A : NumericAlgebra = antiderivativeBy(algebra, variables.toIntArray()) + +// endregion \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt index 1a3eb7874..4d99b3a45 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt @@ -121,7 +121,7 @@ public fun Polynomial.antiderivative( ): Polynomial where A : Field, A : NumericAlgebra = algebra { val integratedCoefficients = buildList(coefficients.size + 1) { add(zero) - coefficients.forEachIndexed{ index, t -> add(t / (number(index) + one)) } + coefficients.forEachIndexed{ index, t -> add(t / number(index + 1)) } } Polynomial(integratedCoefficients) } @@ -136,4 +136,6 @@ public fun > Polynomial.integrate( ): C = algebra { val integral = antiderivative(algebra) integral.substitute(algebra, range.endInclusive) - integral.substitute(algebra, range.start) -} \ No newline at end of file +} + +// endregion \ No newline at end of file -- 2.34.1 From 033edd3febfc36983a1fd6319941ba453531b6f5 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sun, 13 Mar 2022 03:55:51 +0300 Subject: [PATCH 017/275] Removed kotlin-js-store --- kotlin-js-store/yarn.lock | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 kotlin-js-store/yarn.lock diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock deleted file mode 100644 index e69de29bb..000000000 -- 2.34.1 From de53d032afbe7da603b7bc7cc919718c0c193811 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Mon, 14 Mar 2022 14:14:24 +0300 Subject: [PATCH 018/275] 1. Prototyped Rational Functions 2. Added abstract interfaces for removing boilerplates 3. Changed or added default values in interfaces 4. Renamed non-operator `equals` to `equalsTo`, and made it infix --- .../kmath/functions/AbstractPolynomial.kt | 128 ++++- .../functions/AbstractRationalFunction.kt | 500 ++++++++++++++++-- .../kmath/functions/LabeledPolynomial.kt | 24 +- .../kmath/functions/NumberedPolynomial.kt | 74 +-- .../kscience/kmath/functions/Polynomial.kt | 51 +- .../kmath/functions/RationalFunction.kt | 355 +++++++++++++ .../kmath/functions/rationalFunctionUtil.kt | 34 ++ 7 files changed, 998 insertions(+), 168 deletions(-) create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/rationalFunctionUtil.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt index b7b7116f0..69c45798a 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt @@ -154,7 +154,7 @@ public interface AbstractPolynomialSpace> : Ring

* Check if the instant is NOT zero constant. */ @JvmName("constantIsNotZero") - public fun C.isNotZero(): Boolean + public fun C.isNotZero(): Boolean = !isZero() /** * Check if the instant is unit constant. */ @@ -164,7 +164,7 @@ public interface AbstractPolynomialSpace> : Ring

* Check if the instant is NOT unit constant. */ @JvmName("constantIsNotOne") - public fun C.isNotOne(): Boolean + public fun C.isNotOne(): Boolean = !isOne() /** * Check if the instant is minus unit constant. */ @@ -174,7 +174,7 @@ public interface AbstractPolynomialSpace> : Ring

* Check if the instant is NOT minus unit constant. */ @JvmName("constantIsNotMinusOne") - public fun C.isNotMinusOne(): Boolean + public fun C.isNotMinusOne(): Boolean = !isMinusOne() // endregion // region Constant-polynomial relation @@ -232,27 +232,27 @@ public interface AbstractPolynomialSpace> : Ring

/** * Check if the instant is zero polynomial. */ - public fun P.isZero(): Boolean = this == zero + public fun P.isZero(): Boolean = this equalsTo zero /** * Check if the instant is NOT zero polynomial. */ - public fun P.isNotZero(): Boolean = this != zero + public fun P.isNotZero(): Boolean = !isZero() /** * Check if the instant is unit polynomial. */ - public fun P.isOne(): Boolean = this == one + public fun P.isOne(): Boolean = this equalsTo one /** * Check if the instant is NOT unit polynomial. */ - public fun P.isNotOne(): Boolean = this != one + public fun P.isNotOne(): Boolean = !isOne() /** * Check if the instant is minus unit polynomial. */ - public fun P.isMinusOne(): Boolean = this == -one + public fun P.isMinusOne(): Boolean = this equalsTo -one /** * Check if the instant is NOT minus unit polynomial. */ - public fun P.isNotMinusOne(): Boolean = this != -one + public fun P.isNotMinusOne(): Boolean = !isMinusOne() /** * Instance of zero polynomial (zero of the polynomial ring). @@ -266,8 +266,11 @@ public interface AbstractPolynomialSpace> : Ring

/** * Checks equality of the polynomials. */ - @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") - public fun P.equals(other: P): Boolean + public infix fun P.equalsTo(other: P): Boolean + /** + * Checks NOT equality of the polynomials. + */ + public infix fun P.notEqualsTo(other: P): Boolean = !(this equalsTo other) // endregion // Not sure is it necessary... @@ -310,4 +313,107 @@ public interface AbstractPolynomialSpace> : Ring

override fun add(left: P, right: P): P = left + right override fun multiply(left: P, right: P): P = left * right // endregion +} + +/** + * 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 a coefficients in their terms. + * @param P the type of polynomials. + */ +@Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") +public interface AbstractPolynomialSpaceOverRing, A: Ring> : AbstractPolynomialSpace { + + public val ring: A + + // region Constant-integer relation + /** + * Returns sum of the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. + */ + @JvmName("constantIntPlus") + public override operator fun C.plus(other: Int): C = ring { optimizedAddMultiplied(this@plus, one, other) } + /** + * Returns difference between the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. + */ + @JvmName("constantIntMinus") + public override operator fun C.minus(other: Int): C = ring { optimizedAddMultiplied(this@minus, one, -other) } + /** + * Returns product of the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + @JvmName("constantIntTimes") + public override operator fun C.times(other: Int): C = ring { optimizedMultiply(this@times, other) } + // endregion + + // region Integer-constant relation + /** + * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. + */ + @JvmName("intConstantPlus") + public override operator fun Int.plus(other: C): C = ring { optimizedAddMultiplied(other, one, this@plus) } + /** + * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. + */ + @JvmName("intConstantMinus") + public override operator fun Int.minus(other: C): C = ring { optimizedAddMultiplied(-other, one, this@minus) } + /** + * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + @JvmName("intConstantTimes") + public override operator fun Int.times(other: C): C = ring { optimizedMultiply(other, this@times) } + // endregion + + // region Constant-constant relation + /** + * Returns negation of the constant. + */ + @JvmName("constantUnaryMinus") + @JsName("constantUnaryMinus") + public override operator fun C.unaryMinus(): C = ring { -this@unaryMinus } + /** + * Returns sum of the constants. + */ + @JvmName("constantPlus") + @JsName("constantPlus") + public override operator fun C.plus(other: C): C = ring { this@plus + other } + /** + * Returns difference of the constants. + */ + @JvmName("constantMinus") + @JsName("constantMinus") + public override operator fun C.minus(other: C): C = ring { this@minus - other } + /** + * Returns product of the constants. + */ + @JvmName("constantTimes") + @JsName("constantTimes") + public override operator fun C.times(other: C): C = ring { this@times * other } + + /** + * Check if the instant is zero constant. + */ + @JvmName("constantIsZero") + public override fun C.isZero(): Boolean = ring { this == zero } + /** + * Check if the instant is unit constant. + */ + @JvmName("constantIsOne") + public override fun C.isOne(): Boolean = ring { this == one } + /** + * Check if the instant is minus unit constant. + */ + @JvmName("constantIsMinusOne") + public override fun C.isMinusOne(): Boolean = ring { this == -one } + // endregion } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt index 34050aa0f..9725ea078 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt @@ -13,7 +13,12 @@ import kotlin.jvm.JvmName /** * Abstraction of rational function. */ -public interface AbstractRationalFunction> +public interface AbstractRationalFunction> { + public val numerator: P + public val denominator: P + public operator fun component1(): P = numerator + public operator fun component2(): P = denominator +} @Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") public interface AbstractRationalFunctionalSpace, R: AbstractRationalFunction> : Ring { @@ -190,7 +195,7 @@ public interface AbstractRationalFunctionalSpace, R: * Check if the instant is NOT zero constant. */ @JvmName("constantIsNotZero") - public fun C.isNotZero(): Boolean + public fun C.isNotZero(): Boolean = !isZero() /** * Check if the instant is unit constant. */ @@ -200,7 +205,7 @@ public interface AbstractRationalFunctionalSpace, R: * Check if the instant is NOT unit constant. */ @JvmName("constantIsNotOne") - public fun C.isNotOne(): Boolean + public fun C.isNotOne(): Boolean = !isOne() /** * Check if the instant is minus unit constant. */ @@ -210,7 +215,7 @@ public interface AbstractRationalFunctionalSpace, R: * Check if the instant is NOT minus unit constant. */ @JvmName("constantIsNotMinusOne") - public fun C.isNotMinusOne(): Boolean + public fun C.isNotMinusOne(): Boolean = !isMinusOne() // endregion // region Constant-polynomial relation @@ -268,42 +273,45 @@ public interface AbstractRationalFunctionalSpace, R: /** * Check if the instant is zero polynomial. */ - public fun P.isZero(): Boolean = this == zeroPolynomial + public fun P.isZero(): Boolean = this equalsTo polynomialZero /** * Check if the instant is NOT zero polynomial. */ - public fun P.isNotZero(): Boolean = this != zeroPolynomial + public fun P.isNotZero(): Boolean = !isZero() /** * Check if the instant is unit polynomial. */ - public fun P.isOne(): Boolean = this == onePolynomial + public fun P.isOne(): Boolean = this equalsTo polynomialOne /** * Check if the instant is NOT unit polynomial. */ - public fun P.isNotOne(): Boolean = this != onePolynomial + public fun P.isNotOne(): Boolean = !isOne() /** * Check if the instant is minus unit polynomial. */ - public fun P.isMinusOne(): Boolean = this == -onePolynomial + public fun P.isMinusOne(): Boolean = this equalsTo -polynomialOne /** * Check if the instant is NOT minus unit polynomial. */ - public fun P.isNotMinusOne(): Boolean = this != -onePolynomial + public fun P.isNotMinusOne(): Boolean = !isMinusOne() /** * Instance of zero polynomial (zero of the polynomial ring). */ - public val zeroPolynomial: P + public val polynomialZero: P /** * Instance of unit polynomial (unit of the polynomial ring). */ - public val onePolynomial: P + public val polynomialOne: P /** * Checks equality of the polynomials. */ - @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") - public fun P.equals(other: P): Boolean + public infix fun P.equalsTo(other: P): Boolean + /** + * Checks NOT equality of the polynomials. + */ + public infix fun P.notEqualsTo(other: P): Boolean = !(this equalsTo other) // endregion // region Constant-rational relation @@ -391,27 +399,27 @@ public interface AbstractRationalFunctionalSpace, R: /** * Check if the instant is zero rational function. */ - public fun R.isZero(): Boolean = this == zero + public fun R.isZero(): Boolean = this equalsTo zero /** * Check if the instant is NOT zero rational function. */ - public fun R.isNotZero(): Boolean = this != zero + public fun R.isNotZero(): Boolean = !isZero() /** * Check if the instant is unit rational function. */ - public fun R.isOne(): Boolean = this == one + public fun R.isOne(): Boolean = this equalsTo one /** * Check if the instant is NOT unit rational function. */ - public fun R.isNotOne(): Boolean = this != one + public fun R.isNotOne(): Boolean = !isOne() /** * Check if the instant is minus unit rational function. */ - public fun R.isMinusOne(): Boolean = this == -one + public fun R.isMinusOne(): Boolean = this equalsTo -one /** * Check if the instant is NOT minus unit rational function. */ - public fun R.isNotMinusOne(): Boolean = this != -one + public fun R.isNotMinusOne(): Boolean = !isMinusOne() /** * Instance of zero rational function (zero of the rational functions ring). @@ -425,8 +433,11 @@ public interface AbstractRationalFunctionalSpace, R: /** * Checks equality of the rational functions. */ - @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") - public fun R.equals(other: R): Boolean + public infix fun R.equalsTo(other: R): Boolean + /** + * Checks NOT equality of the polynomials. + */ + public infix fun R.notEqualsTo(other: R): Boolean = !(this equalsTo other) // endregion // Not sure is it necessary... @@ -453,35 +464,31 @@ public interface AbstractRationalFunctionalSpace, R: * Checks if the instant is **not** constant non-zero polynomial (of degree no more than 0) over considered ring. */ public fun P.isNotNonZeroConstant(): Boolean = !isNonZeroConstant() - + /** + * If polynomial is a constant polynomial represents and returns it as constant. + * Otherwise, (when the polynomial is not constant polynomial) returns `null`. + */ public fun P.asConstantOrNull(): C? - + /** + * If polynomial is a constant polynomial represents and returns it as constant. + * Otherwise, (when the polynomial is not constant polynomial) raises corresponding exception. + */ public fun P.asConstant(): C = asConstantOrNull() ?: error("Can not represent non-constant polynomial as a constant") // endregion // Not sure is it necessary... - // region Polynomial properties + // region Rational properties /** - * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. + * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is + * zero, degree is -1. */ - public fun R.isConstant(): Boolean + public val R.numeratorDegree: Int get() = numerator.degree /** - * Checks if the instant is **not** constant polynomial (of degree no more than 0) over considered ring. + * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is + * zero, degree is -1. */ - public fun R.isNotConstant(): Boolean = !isConstant() - /** - * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. - */ - public fun R.isNonZeroConstant(): Boolean - /** - * Checks if the instant is **not** constant non-zero polynomial (of degree no more than 0) over considered ring. - */ - public fun R.isNotNonZeroConstant(): Boolean = !isNonZeroConstant() - - public fun R.asConstantOrNull(): C? - - public fun R.asConstant(): C = asConstantOrNull() ?: error("Can not represent non-constant polynomial as a constant") + public val R.denominatorDegree: Int get() = denominator.degree // TODO: Перенести в реализацию // fun R.substitute(argument: C): C @@ -501,5 +508,416 @@ public interface AbstractRationalFunctionalSpace, R: // region Legacy override fun add(left: R, right: R): R = left + right override fun multiply(left: R, right: R): R = left * right + // endregion +} + +@Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") +public interface AbstractRationalFunctionalSpaceOverRing, R: AbstractRationalFunction, A: Ring> : AbstractRationalFunctionalSpace { + + public val ring: A + + // region Constant-integer relation + /** + * Returns sum of the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. + */ + @JvmName("constantIntPlus") + public override operator fun C.plus(other: Int): C = ring { optimizedAddMultiplied(this@plus, one, other) } + /** + * Returns difference between the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. + */ + @JvmName("constantIntMinus") + public override operator fun C.minus(other: Int): C = ring { optimizedAddMultiplied(this@minus, one, -other) } + /** + * Returns product of the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + @JvmName("constantIntTimes") + public override operator fun C.times(other: Int): C = ring { optimizedMultiply(this@times, other) } + // endregion + + // region Integer-constant relation + /** + * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. + */ + @JvmName("intConstantPlus") + public override operator fun Int.plus(other: C): C = ring { optimizedAddMultiplied(other, one, this@plus) } + /** + * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. + */ + @JvmName("intConstantMinus") + public override operator fun Int.minus(other: C): C = ring { optimizedAddMultiplied(-other, one, this@minus) } + /** + * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + @JvmName("intConstantTimes") + public override operator fun Int.times(other: C): C = ring { optimizedMultiply(other, this@times) } + // endregion + + // region Constant-constant relation + /** + * Returns the same constant. + */ + @JvmName("constantUnaryPlus") + @JsName("constantUnaryPlus") + public override operator fun C.unaryPlus(): C = ring { +this@unaryPlus } + /** + * Returns negation of the constant. + */ + @JvmName("constantUnaryMinus") + @JsName("constantUnaryMinus") + public override operator fun C.unaryMinus(): C = ring { -this@unaryMinus } + /** + * Returns sum of the constants. + */ + @JvmName("constantPlus") + @JsName("constantPlus") + public override operator fun C.plus(other: C): C = ring { this@plus + other } + /** + * Returns difference of the constants. + */ + @JvmName("constantMinus") + @JsName("constantMinus") + public override operator fun C.minus(other: C): C = ring { this@minus - other } + /** + * Returns product of the constants. + */ + @JvmName("constantTimes") + @JsName("constantTimes") + public override operator fun C.times(other: C): C = ring { this@times * other } + + /** + * Check if the instant is zero constant. + */ + @JvmName("constantIsZero") + public override fun C.isZero(): Boolean = ring { this@isZero.isZero() } + /** + * Check if the instant is NOT zero constant. + */ + @JvmName("constantIsNotZero") + public override fun C.isNotZero(): Boolean = ring { this@isNotZero.isNotZero() } + /** + * Check if the instant is unit constant. + */ + @JvmName("constantIsOne") + public override fun C.isOne(): Boolean = ring { this@isOne.isOne() } + /** + * Check if the instant is NOT unit constant. + */ + @JvmName("constantIsNotOne") + public override fun C.isNotOne(): Boolean = ring { this@isNotOne.isNotOne() } + /** + * Check if the instant is minus unit constant. + */ + @JvmName("constantIsMinusOne") + public override fun C.isMinusOne(): Boolean = ring { this@isMinusOne.isMinusOne() } + /** + * Check if the instant is NOT minus unit constant. + */ + @JvmName("constantIsNotMinusOne") + public override fun C.isNotMinusOne(): Boolean = ring { this@isNotMinusOne.isNotMinusOne() } + // endregion +} + +@Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") +public interface AbstractRationalFunctionalSpaceOverPolynomialSpace, R: AbstractRationalFunction, A: Ring> : AbstractRationalFunctionalSpace { + + public val polynomialRing: AbstractPolynomialSpace + + // region Constant-integer relation + /** + * Returns sum of the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. + */ + @JvmName("constantIntPlus") + public override operator fun C.plus(other: Int): C = polynomialRing { this@plus + other } + /** + * Returns difference between the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. + */ + @JvmName("constantIntMinus") + public override operator fun C.minus(other: Int): C = polynomialRing { this@minus - other } + /** + * Returns product of the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + @JvmName("constantIntTimes") + public override operator fun C.times(other: Int): C = polynomialRing { this@times * other } + // endregion + + // region Integer-constant relation + /** + * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. + */ + @JvmName("intConstantPlus") + public override operator fun Int.plus(other: C): C = polynomialRing { this@plus + other } + /** + * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. + */ + @JvmName("intConstantMinus") + public override operator fun Int.minus(other: C): C = polynomialRing { this@minus - other } + /** + * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + @JvmName("intConstantTimes") + public override operator fun Int.times(other: C): C = polynomialRing { this@times * other } + // endregion + + // region Polynomial-integer relation + /** + * Returns sum of the constant and the integer represented as polynomial. + * + * The operation is equivalent to adding [other] copies of unit polynomial to [this]. + */ + public override operator fun P.plus(other: Int): P = polynomialRing { this@plus + other } + /** + * Returns difference between the constant and the integer represented as polynomial. + * + * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. + */ + public override operator fun P.minus(other: Int): P = polynomialRing { this@minus - other } + /** + * Returns product of the constant and the integer represented as polynomial. + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + public override operator fun P.times(other: Int): P = polynomialRing { this@times * other } + // endregion + + // region Integer-polynomial relation + /** + * Returns sum of the integer represented as polynomial and the constant. + * + * The operation is equivalent to adding [this] copies of unit polynomial to [other]. + */ + public override operator fun Int.plus(other: P): P = polynomialRing { this@plus + other } + /** + * Returns difference between the integer represented as polynomial and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit polynomial from [other]. + */ + public override operator fun Int.minus(other: P): P = polynomialRing { this@minus - other } + /** + * Returns product of the integer represented as polynomial and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + public override operator fun Int.times(other: P): P = polynomialRing { this@times * other } + // endregion + + // region Constant-constant relation + /** + * Returns the same constant. + */ + @JvmName("constantUnaryPlus") + @JsName("constantUnaryPlus") + public override operator fun C.unaryPlus(): C = polynomialRing { +this@unaryPlus } + /** + * Returns negation of the constant. + */ + @JvmName("constantUnaryMinus") + @JsName("constantUnaryMinus") + public override operator fun C.unaryMinus(): C = polynomialRing { -this@unaryMinus } + /** + * Returns sum of the constants. + */ + @JvmName("constantPlus") + @JsName("constantPlus") + public override operator fun C.plus(other: C): C = polynomialRing { this@plus + other } + /** + * Returns difference of the constants. + */ + @JvmName("constantMinus") + @JsName("constantMinus") + public override operator fun C.minus(other: C): C = polynomialRing { this@minus - other } + /** + * Returns product of the constants. + */ + @JvmName("constantTimes") + @JsName("constantTimes") + public override operator fun C.times(other: C): C = polynomialRing { this@times * other } + + /** + * Check if the instant is zero constant. + */ + @JvmName("constantIsZero") + public override fun C.isZero(): Boolean = polynomialRing { this@isZero.isZero() } + /** + * Check if the instant is NOT zero constant. + */ + @JvmName("constantIsNotZero") + public override fun C.isNotZero(): Boolean = polynomialRing { this@isNotZero.isNotZero() } + /** + * Check if the instant is unit constant. + */ + @JvmName("constantIsOne") + public override fun C.isOne(): Boolean = polynomialRing { this@isOne.isOne() } + /** + * Check if the instant is NOT unit constant. + */ + @JvmName("constantIsNotOne") + public override fun C.isNotOne(): Boolean = polynomialRing { this@isNotOne.isNotOne() } + /** + * Check if the instant is minus unit constant. + */ + @JvmName("constantIsMinusOne") + public override fun C.isMinusOne(): Boolean = polynomialRing { this@isMinusOne.isMinusOne() } + /** + * Check if the instant is NOT minus unit constant. + */ + @JvmName("constantIsNotMinusOne") + public override fun C.isNotMinusOne(): Boolean = polynomialRing { this@isNotMinusOne.isNotMinusOne() } + // endregion + + // region Constant-polynomial relation + /** + * Returns sum of the constant represented as polynomial and the polynomial. + */ + public override operator fun C.plus(other: P): P = polynomialRing { this@plus + other } + /** + * Returns difference between the constant represented as polynomial and the polynomial. + */ + public override operator fun C.minus(other: P): P = polynomialRing { this@minus - other } + /** + * Returns product of the constant represented as polynomial and the polynomial. + */ + public override operator fun C.times(other: P): P = polynomialRing { this@times * other } + // endregion + + // region Polynomial-constant relation + /** + * Returns sum of the constant represented as polynomial and the polynomial. + */ + public override operator fun P.plus(other: C): P = polynomialRing { this@plus + other } + /** + * Returns difference between the constant represented as polynomial and the polynomial. + */ + public override operator fun P.minus(other: C): P = polynomialRing { this@minus - other } + /** + * Returns product of the constant represented as polynomial and the polynomial. + */ + public override operator fun P.times(other: C): P = polynomialRing { this@times * other } + // endregion + + // region Polynomial-polynomial relation + /** + * Returns the same polynomial. + */ + public override operator fun P.unaryPlus(): P = polynomialRing { +this@unaryPlus } + /** + * Returns negation of the polynomial. + */ + public override operator fun P.unaryMinus(): P = polynomialRing { -this@unaryMinus } + /** + * Returns sum of the polynomials. + */ + public override operator fun P.plus(other: P): P = polynomialRing { this@plus + other } + /** + * Returns difference of the polynomials. + */ + public override operator fun P.minus(other: P): P = polynomialRing { this@minus - other } + /** + * Returns product of the polynomials. + */ + public override operator fun P.times(other: P): P = polynomialRing { this@times * other } + + /** + * Check if the instant is zero polynomial. + */ + public override fun P.isZero(): Boolean = polynomialRing { this@isZero.isZero() } + /** + * Check if the instant is NOT zero polynomial. + */ + public override fun P.isNotZero(): Boolean = polynomialRing { this@isNotZero.isNotZero() } + /** + * Check if the instant is unit polynomial. + */ + public override fun P.isOne(): Boolean = polynomialRing { this@isOne.isOne() } + /** + * Check if the instant is NOT unit polynomial. + */ + public override fun P.isNotOne(): Boolean = polynomialRing { this@isNotOne.isNotOne() } + /** + * Check if the instant is minus unit polynomial. + */ + public override fun P.isMinusOne(): Boolean = polynomialRing { this@isMinusOne.isMinusOne() } + /** + * Check if the instant is NOT minus unit polynomial. + */ + public override fun P.isNotMinusOne(): Boolean = polynomialRing { this@isNotMinusOne.isNotMinusOne() } + + /** + * 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 + + /** + * Checks equality of the polynomials. + */ + public override infix fun P.equalsTo(other: P): Boolean = polynomialRing { this@equalsTo equalsTo other } + /** + * Checks NOT equality of the polynomials. + */ + public override infix fun P.notEqualsTo(other: P): Boolean = polynomialRing { this@notEqualsTo notEqualsTo other } + // endregion + + // Not sure is it necessary... + // region Polynomial properties + /** + * 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 } + + /** + * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. + */ + public override fun P.isConstant(): Boolean = polynomialRing { this@isConstant.isConstant() } + /** + * Checks if the instant is **not** constant polynomial (of degree no more than 0) over considered ring. + */ + public override fun P.isNotConstant(): Boolean = polynomialRing { this@isNotConstant.isNotConstant() } + /** + * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. + */ + public override fun P.isNonZeroConstant(): Boolean = polynomialRing { this@isNonZeroConstant.isNonZeroConstant() } + /** + * Checks if the instant is **not** constant non-zero polynomial (of degree no more than 0) over considered ring. + */ + public override fun P.isNotNonZeroConstant(): Boolean = polynomialRing { this@isNotNonZeroConstant.isNotNonZeroConstant() } + /** + * If polynomial is a constant polynomial represents and returns it as constant. + * Otherwise, (when the polynomial is not constant polynomial) returns `null`. + */ + public override fun P.asConstantOrNull(): C? = polynomialRing { this@asConstantOrNull.asConstantOrNull() } + /** + * If polynomial is a constant polynomial represents and returns it as constant. + * Otherwise, (when the polynomial is not constant polynomial) raises corresponding exception. + */ + public override fun P.asConstant(): C = polynomialRing { this@asConstant.asConstant() } + // endregion } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt index 48f6f57fa..cbd713d27 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -13,7 +13,7 @@ import kotlin.math.max * * @param C Ring in which the polynomial is considered. */ -public class LabeledPolynomial +public data class LabeledPolynomial internal constructor( /** * Map that collects coefficients of the polynomial. Every non-zero monomial @@ -788,7 +788,7 @@ public class LabeledPolynomialSpace>( isZero() -> zero other.isZero() -> zero else -> LabeledPolynomial( - buildCoefficients { + buildCoefficients(coefficients.size * other.coefficients.size) { for ((degs1, c1) in coefficients) for ((degs2, c2) in other.coefficients) { val degs = degs1.toMutableMap() degs2.mapValuesTo(degs) { (variable, deg) -> degs.getOrElse(variable) { 0u } + deg } @@ -804,7 +804,7 @@ public class LabeledPolynomialSpace>( // TODO: Docs @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") - override fun LabeledPolynomial.equals(other: LabeledPolynomial): Boolean = + override infix fun LabeledPolynomial.equalsTo(other: LabeledPolynomial): Boolean = when { this === other -> true else -> coefficients.size == other.coefficients.size && @@ -896,15 +896,9 @@ public class LabeledPolynomialSpace>( // public inline operator fun LabeledPolynomial.invoke(argument: Map>): LabeledPolynomial = this.substitute(ring, argument) // endregion - // region Legacy - @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") - override inline fun add(left: LabeledPolynomial, right: LabeledPolynomial): LabeledPolynomial = left + right - @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") - override inline fun multiply(left: LabeledPolynomial, right: LabeledPolynomial): LabeledPolynomial = left * right - // endregion - // region Utilities // TODO: Move to region internal utilities with context receiver + @JvmName("applyAndRemoveZerosInternal") internal fun MutableMap, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : MutableMap, C> { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) @@ -916,12 +910,20 @@ public class LabeledPolynomialSpace>( internal fun Map, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : Map, C> = toMutableMap().applyAndRemoveZeros(block) @OptIn(ExperimentalTypeInference::class) - internal fun buildCoefficients(@BuilderInference builderAction: MutableMap, C>.() -> Unit): Map, C> { + internal inline fun buildCoefficients(@BuilderInference builderAction: MutableMap, C>.() -> Unit): Map, C> { contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } return buildMap { builderAction() for ((degs, c) in this) if (c.isZero()) this.remove(degs) } } + @OptIn(ExperimentalTypeInference::class) + internal inline fun buildCoefficients(capacity: Int, @BuilderInference builderAction: MutableMap, C>.() -> Unit): Map, C> { + contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } + return buildMap(capacity) { + builderAction() + for ((degs, c) in this) if (c.isZero()) this.remove(degs) + } + } // endregion } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index f1ad9a74f..f11338161 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -13,7 +13,7 @@ import kotlin.math.max * * @param C the type of constants. */ -public class NumberedPolynomial +public data class NumberedPolynomial internal constructor( /** * Map that collects coefficients of the polynomial. Every monomial `a x_1^{d_1} ... x_n^{d_n}` is represented as @@ -259,27 +259,9 @@ public fun > C.asNumberedPolynomial() : NumberedPolynomial = Nu * @param ring the [A] instance. */ @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE", "INAPPLICABLE_JVM_NAME") -public class NumberedPolynomialSpace>( - public val ring: A, -) : AbstractPolynomialSpace> { - // region Constant-integer relation - @JvmName("constantIntPlus") - public override operator fun C.plus(other: Int): C = ring { optimizedAddMultiplied(this@plus, one, other) } - @JvmName("constantIntMinus") - public override operator fun C.minus(other: Int): C = ring { optimizedAddMultiplied(this@minus, one, -other) } - @JvmName("constantIntTimes") - public override operator fun C.times(other: Int): C = ring { optimizedMultiply(this@times, other) } - // endregion - - // region Integer-constant relation - @JvmName("intConstantPlus") - public override operator fun Int.plus(other: C): C = ring { optimizedAddMultiplied(other, one, this@plus) } - @JvmName("intConstantMinus") - public override operator fun Int.minus(other: C): C = ring { optimizedAddMultiplied(-other, one, this@minus) } - @JvmName("intConstantTimes") - public override operator fun Int.times(other: C): C = ring { optimizedMultiply(other, this@times) } - // endregion - +public open class NumberedPolynomialSpace>( + public final override val ring: A, +) : AbstractPolynomialSpaceOverRing, A> { // region Polynomial-integer relation public override operator fun NumberedPolynomial.plus(other: Int): NumberedPolynomial = if (other == 0) this @@ -362,29 +344,6 @@ public class NumberedPolynomialSpace>( ) // endregion - // region Constant-constant relation - @JvmName("constantUnaryMinus") - override operator fun C.unaryMinus(): C = ring { -this@unaryMinus } - @JvmName("constantPlus") - override operator fun C.plus(other: C): C = ring { this@plus + other } - @JvmName("constantMinus") - override operator fun C.minus(other: C): C = ring { this@minus - other } - @JvmName("constantTimes") - override operator fun C.times(other: C): C = ring { this@times * other } - @JvmName("constantIsZero") - public override fun C.isZero(): Boolean = ring { this == zero } - @JvmName("constantIsNotZero") - public override fun C.isNotZero(): Boolean = ring { this != zero } - @JvmName("constantIsOne") - public override fun C.isOne(): Boolean = ring { this == one } - @JvmName("constantIsNotOne") - public override fun C.isNotOne(): Boolean = ring { this != one } - @JvmName("constantIsMinusOne") - public override fun C.isMinusOne(): Boolean = ring { this == -one } - @JvmName("constantIsNotMinusOne") - public override fun C.isNotMinusOne(): Boolean = ring { this != -one } - // endregion - // region Constant-polynomial relation override operator fun C.plus(other: NumberedPolynomial): NumberedPolynomial = if (this.isZero()) other @@ -521,7 +480,7 @@ public class NumberedPolynomialSpace>( other.isZero() -> zero else -> NumberedPolynomial( - buildCoefficients { + buildCoefficients(coefficients.size * other.coefficients.size) { for ((degs1, c1) in coefficients) for ((degs2, c2) in other.coefficients) { val degs = (0..max(degs1.lastIndex, degs2.lastIndex)) @@ -534,7 +493,6 @@ public class NumberedPolynomialSpace>( } public override fun NumberedPolynomial.isZero(): Boolean = coefficients.values.all { it.isZero() } - public override fun NumberedPolynomial.isNotZero(): Boolean = coefficients.values.any { it.isNotZero() } public override fun NumberedPolynomial.isOne(): Boolean = with(coefficients) { var foundAbsoluteTermAndItIsOne = false @@ -547,7 +505,6 @@ public class NumberedPolynomialSpace>( } foundAbsoluteTermAndItIsOne } - public override fun NumberedPolynomial.isNotOne(): Boolean = !isOne() public override fun NumberedPolynomial.isMinusOne(): Boolean = with(coefficients) { var foundAbsoluteTermAndItIsMinusOne = false @@ -560,7 +517,6 @@ public class NumberedPolynomialSpace>( } foundAbsoluteTermAndItIsMinusOne } - public override fun NumberedPolynomial.isNotMinusOne(): Boolean = !isMinusOne() override val zero: NumberedPolynomial = NumberedPolynomial(emptyMap()) override val one: NumberedPolynomial = @@ -572,7 +528,7 @@ public class NumberedPolynomialSpace>( // TODO: Docs @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") - override fun NumberedPolynomial.equals(other: NumberedPolynomial): Boolean = + override infix fun NumberedPolynomial.equalsTo(other: NumberedPolynomial): Boolean = when { this === other -> true else -> coefficients.size == other.coefficients.size && @@ -658,15 +614,9 @@ public class NumberedPolynomialSpace>( public inline operator fun NumberedPolynomial.invoke(argument: Map>): NumberedPolynomial = this.substitute(ring, argument) // endregion - // region Legacy - @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") - override inline fun add(left: NumberedPolynomial, right: NumberedPolynomial): NumberedPolynomial = left + right - @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") - override inline fun multiply(left: NumberedPolynomial, right: NumberedPolynomial): NumberedPolynomial = left * right - // endregion - // region Utilities // TODO: Move to region internal utilities with context receiver + @JvmName("applyAndRemoveZerosInternal") internal fun MutableMap, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : MutableMap, C> { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) @@ -678,12 +628,20 @@ public class NumberedPolynomialSpace>( internal fun Map, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : Map, C> = toMutableMap().applyAndRemoveZeros(block) @OptIn(ExperimentalTypeInference::class) - internal fun buildCoefficients(@BuilderInference builderAction: MutableMap, C>.() -> Unit): Map, C> { + internal inline fun buildCoefficients(@BuilderInference builderAction: MutableMap, C>.() -> Unit): Map, C> { contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } return buildMap { builderAction() for ((degs, c) in this) if (c.isZero()) this.remove(degs) } } + @OptIn(ExperimentalTypeInference::class) + internal inline fun buildCoefficients(capacity: Int, @BuilderInference builderAction: MutableMap, C>.() -> Unit): Map, C> { + contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } + return buildMap(capacity) { + builderAction() + for ((degs, c) in this) if (c.isZero()) this.remove(degs) + } + } // endregion } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 99d6b0659..2c764f4f5 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -15,7 +15,7 @@ import kotlin.math.min * * @param coefficients constant is the leftmost coefficient. */ -public class Polynomial(public val coefficients: List) : AbstractPolynomial { +public data class Polynomial(public val coefficients: List) : AbstractPolynomial { override fun toString(): String = "Polynomial$coefficients" } @@ -69,25 +69,8 @@ public fun T.asPolynomial() : Polynomial = Polynomial(listOf(this)) */ @Suppress("INAPPLICABLE_JVM_NAME") // TODO: KT-31420 public open class PolynomialSpace>( - public val ring: A, -) : AbstractPolynomialSpace> { - // region Constant-integer relation - @JvmName("constantIntPlus") - public override operator fun C.plus(other: Int): C = ring { optimizedAddMultiplied(this@plus, one, other) } - @JvmName("constantIntMinus") - public override operator fun C.minus(other: Int): C = ring { optimizedAddMultiplied(this@minus, one, -other) } - @JvmName("constantIntTimes") - public override operator fun C.times(other: Int): C = ring { optimizedMultiply(this@times, other) } - // endregion - - // region Integer-constant relation - @JvmName("intConstantPlus") - public override operator fun Int.plus(other: C): C = ring { optimizedAddMultiplied(other, one, this@plus) } - @JvmName("intConstantMinus") - public override operator fun Int.minus(other: C): C = ring { optimizedAddMultiplied(-other, one, this@minus) } - @JvmName("intConstantTimes") - public override operator fun Int.times(other: C): C = ring { optimizedMultiply(other, this@times) } - // endregion + public final override val ring: A, +) : AbstractPolynomialSpaceOverRing, A> { // region Polynomial-integer relation public override operator fun Polynomial.plus(other: Int): Polynomial = @@ -179,29 +162,6 @@ public open class PolynomialSpace>( ) // endregion - // region Constant-constant relation - @JvmName("constantUnaryMinus") - public override operator fun C.unaryMinus(): C = ring { -this@unaryMinus } - @JvmName("constantPlus") - public override operator fun C.plus(other: C): C = ring { this@plus + other } - @JvmName("constantMinus") - public override operator fun C.minus(other: C): C = ring { this@minus - other } - @JvmName("constantTimes") - public override operator fun C.times(other: C): C = ring { this@times * other } - @JvmName("constantIsZero") - public override fun C.isZero(): Boolean = ring { this == zero } - @JvmName("constantIsNotZero") - public override fun C.isNotZero(): Boolean = ring { this != zero } - @JvmName("constantIsOne") - public override fun C.isOne(): Boolean = ring { this == one } - @JvmName("constantIsNotOne") - public override fun C.isNotOne(): Boolean = ring { this != one } - @JvmName("constantIsMinusOne") - public override fun C.isMinusOne(): Boolean = ring { this == -one } - @JvmName("constantIsNotMinusOne") - public override fun C.isNotMinusOne(): Boolean = ring { this != -one } - // endregion - // region Constant-polynomial relation public override operator fun C.plus(other: Polynomial): Polynomial = if (this.isZero()) other @@ -355,19 +315,16 @@ public open class PolynomialSpace>( } public override fun Polynomial.isZero(): Boolean = coefficients.all { it.isZero() } - public override fun Polynomial.isNotZero(): Boolean = coefficients.any { it.isNotZero() } public override fun Polynomial.isOne(): Boolean = with(coefficients) { isNotEmpty() && asSequence().withIndex().any { (index, c) -> if (index == 0) c.isOne() else c.isZero() } } // TODO: It's better to write new methods like `anyIndexed`. But what's better way to do it? - public override fun Polynomial.isNotOne(): Boolean = !isOne() public override fun Polynomial.isMinusOne(): Boolean = with(coefficients) { isNotEmpty() && asSequence().withIndex().any { (index, c) -> if (index == 0) c.isMinusOne() else c.isZero() } } // TODO: It's better to write new methods like `anyIndexed`. But what's better way to do it? - public override fun Polynomial.isNotMinusOne(): Boolean = !isMinusOne() override val zero: Polynomial = Polynomial(emptyList()) override val one: Polynomial = Polynomial(listOf(ring.one)) @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") - public override fun Polynomial.equals(other: Polynomial): Boolean = + public override infix fun Polynomial.equalsTo(other: Polynomial): Boolean = when { this === other -> true else -> { diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt new file mode 100644 index 000000000..778ffb895 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -0,0 +1,355 @@ +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.* +import kotlin.jvm.JvmName +import kotlin.math.max +import kotlin.math.min + + +public data class RationalFunction internal constructor ( + public override val numerator: Polynomial, + public override val denominator: Polynomial +) : AbstractRationalFunction> { + override fun toString(): String = "RationalFunction${numerator.coefficients}/${denominator.coefficients}" +} + +// region Internal utilities + +/** + * Represents internal [RationalFunction] errors. + */ +internal class RationalFunctionError : Error { + constructor(): super() + constructor(message: String): super(message) + constructor(message: String?, cause: Throwable?): super(message, cause) + constructor(cause: Throwable?): super(cause) +} + +/** + * Throws an [RationalFunction] with the given [message]. + */ +internal fun rationalFunctionError(message: Any): Nothing = throw RationalFunctionError(message.toString()) + +// endregion + +// region Constructors and converters +// Waiting for context receivers :( TODO: Replace with context receivers when they will be available + +//context(RationalFunctionSpace) +//@Suppress("FunctionName") +//internal fun > RationalFunction(numerator: Polynomial, denominator: Polynomial): RationalFunction = +// if (denominator.isZero()) throw ArithmeticException("/ by zero") +// else RationalFunction(numerator, denominator) +//context(RationalFunctionSpace) +//@Suppress("FunctionName") +//public fun > RationalFunction(numeratorCoefficients: List, denominatorCoefficients: List, reverse: Boolean = false): RationalFunction = +// RationalFunction( +// Polynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), +// Polynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } ).also { if (it.isZero()) } +// ) +//context(RationalFunctionSpace) +//@Suppress("FunctionName") +//public fun > RationalFunction(numerator: Polynomial): RationalFunction = +// RationalFunction(numerator, onePolynomial) +//context(RationalFunctionSpace) +//@Suppress("FunctionName") +//public fun > RationalFunction(numeratorCoefficients: List, reverse: Boolean = false): RationalFunction = +// RationalFunction( +// Polynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ) +// ) + +// endregion + +public class RationalFunctionSpace> ( + public val ring: A, +) : AbstractRationalFunctionalSpaceOverPolynomialSpace, RationalFunction, A> { + + override val polynomialRing : PolynomialSpace = PolynomialSpace(ring) + + // region Rational-integer relation + /** + * Returns sum of the rational function and the integer represented as rational function. + * + * The operation is equivalent to adding [other] copies of unit polynomial to [this]. + */ + public override operator fun RationalFunction.plus(other: Int): RationalFunction = + RationalFunction( + numerator + denominator * other, + denominator + ) + /** + * Returns difference between the rational function and the integer represented as rational function. + * + * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. + */ + public override operator fun RationalFunction.minus(other: Int): RationalFunction = + RationalFunction( + numerator - denominator * other, + denominator + ) + /** + * Returns product of the rational function and the integer represented as rational function. + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + public override operator fun RationalFunction.times(other: Int): RationalFunction = + RationalFunction( + numerator * other, + denominator + ) + // endregion + + // region Integer-Rational relation + /** + * Returns sum of the integer represented as 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: RationalFunction): RationalFunction = TODO() + /** + * Returns difference between the integer represented as 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: RationalFunction): RationalFunction = TODO() + /** + * Returns product of the integer represented as rational function and the rational function. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + public override operator fun Int.times(other: RationalFunction): RationalFunction = TODO() + // endregion + + // region Constant-rational relation + /** + * Returns sum of the constant represented as rational function and the rational function. + */ + public override operator fun C.plus(other: RationalFunction): RationalFunction = TODO() + /** + * Returns difference between the constant represented as polynomial and the rational function. + */ + public override operator fun C.minus(other: RationalFunction): RationalFunction = TODO() + /** + * Returns product of the constant represented as polynomial and the rational function. + */ + public override operator fun C.times(other: RationalFunction): RationalFunction = TODO() + // endregion + + // region Rational-constant relation + /** + * Returns sum of the constant represented as rational function and the rational function. + */ + public override operator fun RationalFunction.plus(other: C): RationalFunction = + RationalFunction( + numerator + denominator * other, + denominator + ) + /** + * Returns difference between the constant represented as rational function and the rational function. + */ + public override operator fun RationalFunction.minus(other: C): RationalFunction = + RationalFunction( + numerator - denominator * other, + denominator + ) + /** + * Returns product of the constant represented as rational function and the rational function. + */ + public override operator fun RationalFunction.times(other: C): RationalFunction = + RationalFunction( + numerator * other, + denominator + ) + // endregion + + // region Polynomial-rational relation + /** + * Returns sum of the polynomial represented as rational function and the rational function. + */ + public override operator fun Polynomial.plus(other: RationalFunction): RationalFunction = TODO() + /** + * Returns difference between the polynomial represented as polynomial and the rational function. + */ + public override operator fun Polynomial.minus(other: RationalFunction): RationalFunction = TODO() + /** + * Returns product of the polynomial represented as polynomial and the rational function. + */ + public override operator fun Polynomial.times(other: RationalFunction): RationalFunction = TODO() + // endregion + + // region Rational-polynomial relation + /** + * Returns sum of the polynomial represented as rational function and the rational function. + */ + public override operator fun RationalFunction.plus(other: Polynomial): RationalFunction = + RationalFunction( + numerator + denominator * other, + denominator + ) + /** + * Returns difference between the polynomial represented as rational function and the rational function. + */ + public override operator fun RationalFunction.minus(other: Polynomial): RationalFunction = + RationalFunction( + numerator - denominator * other, + denominator + ) + /** + * Returns product of the polynomial represented as rational function and the rational function. + */ + public override operator fun RationalFunction.times(other: Polynomial): RationalFunction = + RationalFunction( + numerator * other, + denominator + ) + // endregion + + // region Rational-rational relation + /** + * Returns negation of the rational function. + */ + public override operator fun RationalFunction.unaryMinus(): RationalFunction = RationalFunction(-numerator, denominator) + /** + * Returns sum of the rational functions. + */ + public override operator fun RationalFunction.plus(other: RationalFunction): RationalFunction = + RationalFunction( + numerator * other.denominator + denominator * other.numerator, + denominator * other.denominator + ) + /** + * Returns difference of the rational functions. + */ + public override operator fun RationalFunction.minus(other: RationalFunction): RationalFunction = + RationalFunction( + numerator * other.denominator - denominator * other.numerator, + denominator * other.denominator + ) + /** + * Returns product of the rational functions. + */ + public override operator fun RationalFunction.times(other: RationalFunction): RationalFunction = + RationalFunction( + numerator * other.numerator, + denominator * other.denominator + ) + + /** + * Check if the instant is zero rational function. + */ + public override fun RationalFunction.isZero(): Boolean = numerator.isZero() + /** + * Check if the instant is unit rational function. + */ + public override fun RationalFunction.isOne(): Boolean = numerator.equalsTo(denominator) + /** + * Check if the instant is minus unit rational function. + */ + public override fun RationalFunction.isMinusOne(): Boolean = (numerator + denominator).isZero() + + /** + * Instance of zero rational function (zero of the rational functions ring). + */ + public override val zero: RationalFunction = RationalFunction(polynomialZero, polynomialOne) + /** + * Instance of unit polynomial (unit of the rational functions ring). + */ + public override val one: RationalFunction = RationalFunction(polynomialOne, polynomialOne) + + /** + * Checks equality of the rational functions. + */ + @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") + public override infix fun RationalFunction.equalsTo(other: RationalFunction): Boolean = + when { + this === other -> true + numeratorDegree - denominatorDegree != with(other) { numeratorDegree - denominatorDegree } -> false + else -> numerator * other.denominator equalsTo other.numerator * denominator + } + // endregion + + // region REST TODO: Разобрать + + public operator fun RationalFunction.div(other: RationalFunction): RationalFunction = + RationalFunction( + numerator * other.denominator, + denominator * other.numerator + ) + + public operator fun RationalFunction.div(other: Polynomial): RationalFunction = + RationalFunction( + numerator, + denominator * other + ) + + public operator fun RationalFunction.div(other: C): RationalFunction = + RationalFunction( + numerator, + denominator * other + ) + + public operator fun RationalFunction.div(other: Int): RationalFunction = + RationalFunction( + numerator, + denominator * other + ) + +// operator fun invoke(arg: UnivariatePolynomial): RationalFunction = +// RationalFunction( +// numerator(arg), +// denominator(arg) +// ) +// +// operator fun invoke(arg: RationalFunction): RationalFunction { +// val num = numerator invokeRFTakeNumerator arg +// val den = denominator invokeRFTakeNumerator arg +// val degreeDif = numeratorDegree - denominatorDegree +// return if (degreeDif > 0) +// RationalFunction( +// num, +// multiplyByPower(den, arg.denominator, degreeDif) +// ) +// else +// RationalFunction( +// multiplyByPower(num, arg.denominator, -degreeDif), +// den +// ) +// } +// +// override fun toString(): String = toString(UnivariatePolynomial.variableName) +// +// fun toString(withVariableName: String = UnivariatePolynomial.variableName): String = +// when(true) { +// numerator.isZero() -> "0" +// denominator.isOne() -> numerator.toString(withVariableName) +// else -> "${numerator.toStringWithBrackets(withVariableName)}/${denominator.toStringWithBrackets(withVariableName)}" +// } +// +// fun toStringWithBrackets(withVariableName: String = UnivariatePolynomial.variableName): String = +// when(true) { +// numerator.isZero() -> "0" +// denominator.isOne() -> numerator.toStringWithBrackets(withVariableName) +// else -> "(${numerator.toStringWithBrackets(withVariableName)}/${denominator.toStringWithBrackets(withVariableName)})" +// } +// +// fun toReversedString(withVariableName: String = UnivariatePolynomial.variableName): String = +// when(true) { +// numerator.isZero() -> "0" +// denominator.isOne() -> numerator.toReversedString(withVariableName) +// else -> "${numerator.toReversedStringWithBrackets(withVariableName)}/${denominator.toReversedStringWithBrackets(withVariableName)}" +// } +// +// fun toReversedStringWithBrackets(withVariableName: String = UnivariatePolynomial.variableName): String = +// when(true) { +// numerator.isZero() -> "0" +// denominator.isOne() -> numerator.toReversedStringWithBrackets(withVariableName) +// else -> "(${numerator.toReversedStringWithBrackets(withVariableName)}/${denominator.toReversedStringWithBrackets(withVariableName)})" +// } +// +// fun removeZeros() = +// RationalFunction( +// numerator.removeZeros(), +// denominator.removeZeros() +// ) + // endregion +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/rationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/rationalFunctionUtil.kt new file mode 100644 index 000000000..9147bc023 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/rationalFunctionUtil.kt @@ -0,0 +1,34 @@ +package space.kscience.kmath.functions + + +// region Operator extensions + +// region Field case + +//operator fun > RationalFunction.invoke(arg: T): T = numerator(arg) / denominator(arg) +// +//fun > RationalFunction.reduced(): RationalFunction = +// polynomialGCD(numerator, denominator).let { +// RationalFunction( +// numerator / it, +// denominator / it +// ) +// } + +// endregion + +// endregion + +// region Derivatives +///** +// * Returns result of applying formal derivative to the polynomial. +// * +// * @param T Field where we are working now. +// * @return Result of the operator. +// */ +//fun > RationalFunction.derivative() = +// RationalFunction( +// numerator.derivative() * denominator - denominator.derivative() * numerator, +// denominator * denominator +// ) +// endregion \ No newline at end of file -- 2.34.1 From 07f4b83722e2b509f79a212612a952d8a0d64eba Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Mon, 14 Mar 2022 14:18:15 +0300 Subject: [PATCH 019/275] Fixed forgotten TODOs --- .../kmath/functions/RationalFunction.kt | 54 +++++++++++++++---- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index 778ffb895..78ca556db 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -105,34 +105,58 @@ public class RationalFunctionSpace> ( * * The operation is equivalent to adding [this] copies of unit polynomial to [other]. */ - public override operator fun Int.plus(other: RationalFunction): RationalFunction = TODO() + public override operator fun Int.plus(other: RationalFunction): RationalFunction = + RationalFunction( + other.denominator * this + other.numerator, + other.denominator + ) /** * Returns difference between the integer represented as 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: RationalFunction): RationalFunction = TODO() + public override operator fun Int.minus(other: RationalFunction): RationalFunction = + RationalFunction( + other.denominator * this - other.numerator, + other.denominator + ) /** * Returns product of the integer represented as rational function and the rational function. * * The operation is equivalent to sum of [this] copies of [other]. */ - public override operator fun Int.times(other: RationalFunction): RationalFunction = TODO() + public override operator fun Int.times(other: RationalFunction): RationalFunction = + RationalFunction( + this * other.numerator, + other.denominator + ) // endregion // region Constant-rational relation /** * Returns sum of the constant represented as rational function and the rational function. */ - public override operator fun C.plus(other: RationalFunction): RationalFunction = TODO() + public override operator fun C.plus(other: RationalFunction): RationalFunction = + RationalFunction( + other.denominator * this + other.numerator, + other.denominator + ) /** * Returns difference between the constant represented as polynomial and the rational function. */ - public override operator fun C.minus(other: RationalFunction): RationalFunction = TODO() + public override operator fun C.minus(other: RationalFunction): RationalFunction = + RationalFunction( + other.denominator * this - other.numerator, + other.denominator + ) /** * Returns product of the constant represented as polynomial and the rational function. */ - public override operator fun C.times(other: RationalFunction): RationalFunction = TODO() + public override operator fun C.times(other: RationalFunction): RationalFunction = + RationalFunction( + this * other.numerator, + other.denominator + ) // endregion // region Rational-constant relation @@ -166,15 +190,27 @@ public class RationalFunctionSpace> ( /** * Returns sum of the polynomial represented as rational function and the rational function. */ - public override operator fun Polynomial.plus(other: RationalFunction): RationalFunction = TODO() + public override operator fun Polynomial.plus(other: RationalFunction): RationalFunction = + RationalFunction( + other.denominator * this + other.numerator, + other.denominator + ) /** * Returns difference between the polynomial represented as polynomial and the rational function. */ - public override operator fun Polynomial.minus(other: RationalFunction): RationalFunction = TODO() + public override operator fun Polynomial.minus(other: RationalFunction): RationalFunction = + RationalFunction( + other.denominator * this - other.numerator, + other.denominator + ) /** * Returns product of the polynomial represented as polynomial and the rational function. */ - public override operator fun Polynomial.times(other: RationalFunction): RationalFunction = TODO() + public override operator fun Polynomial.times(other: RationalFunction): RationalFunction = + RationalFunction( + this * other.numerator, + other.denominator + ) // endregion // region Rational-polynomial relation -- 2.34.1 From dd820da76579f93e24dcf8cf4216890f04931515 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Mon, 14 Mar 2022 19:59:53 +0300 Subject: [PATCH 020/275] 1. Prototyped rest 2 algebraic structures of rational functions 2. Added `constantZero` and `constantOne` to abstract spaces and applied them instead of `ring.zero` and `ring.one` 3. Moved logic of `R.isZero` and 5 others to `AbstractRationalFunctionalSpace` 4. Deleted forgotten overridden functions of constants 5. Added KMath contributors' copyright notes 6. Added TODO :smile: The `NumberedPolynomial`'s `countOfVariables` is a confusing --- .../kmath/functions/AbstractPolynomial.kt | 30 +- .../functions/AbstractRationalFunction.kt | 60 ++- .../kmath/functions/LabeledPolynomial.kt | 147 +++--- .../functions/LabeledRationalFunction.kt | 464 ++++++++++++++++++ .../kmath/functions/NumberedPolynomial.kt | 26 +- .../functions/NumberedRationalFunction.kt | 453 +++++++++++++++++ .../kscience/kmath/functions/Polynomial.kt | 18 +- .../kmath/functions/RationalFunction.kt | 18 +- .../kmath/functions/labeledPolynomialUtil.kt | 7 +- .../functions/labeledRationalFunctionUtil.kt | 130 +++++ .../functions/numberedRationalFunctionUtil.kt | 23 + .../kmath/functions/rationalFunctionUtil.kt | 5 + 12 files changed, 1211 insertions(+), 170 deletions(-) create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt index 69c45798a..0ca2d1409 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt @@ -149,7 +149,7 @@ public interface AbstractPolynomialSpace> : Ring

* Check if the instant is zero constant. */ @JvmName("constantIsZero") - public fun C.isZero(): Boolean + public fun C.isZero(): Boolean = this == constantZero /** * Check if the instant is NOT zero constant. */ @@ -159,7 +159,7 @@ public interface AbstractPolynomialSpace> : Ring

* Check if the instant is unit constant. */ @JvmName("constantIsOne") - public fun C.isOne(): Boolean + public fun C.isOne(): Boolean = this == constantOne /** * Check if the instant is NOT unit constant. */ @@ -169,12 +169,21 @@ public interface AbstractPolynomialSpace> : Ring

* Check if the instant is minus unit constant. */ @JvmName("constantIsMinusOne") - public fun C.isMinusOne(): Boolean + public fun C.isMinusOne(): Boolean = this == -constantOne /** * Check if the instant is NOT minus unit constant. */ @JvmName("constantIsNotMinusOne") public fun C.isNotMinusOne(): Boolean = !isMinusOne() + + /** + * 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 // endregion // region Constant-polynomial relation @@ -401,19 +410,12 @@ public interface AbstractPolynomialSpaceOverRing, A: public override operator fun C.times(other: C): C = ring { this@times * other } /** - * Check if the instant is zero constant. + * Instance of zero constant (zero of the underlying ring). */ - @JvmName("constantIsZero") - public override fun C.isZero(): Boolean = ring { this == zero } + public override val constantZero: C get() = ring.zero /** - * Check if the instant is unit constant. + * Instance of unit constant (unit of the underlying ring). */ - @JvmName("constantIsOne") - public override fun C.isOne(): Boolean = ring { this == one } - /** - * Check if the instant is minus unit constant. - */ - @JvmName("constantIsMinusOne") - public override fun C.isMinusOne(): Boolean = ring { this == -one } + public override val constantOne: C get() = ring.one // endregion } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt index 9725ea078..df366f90f 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt @@ -190,7 +190,7 @@ public interface AbstractRationalFunctionalSpace, R: * Check if the instant is zero constant. */ @JvmName("constantIsZero") - public fun C.isZero(): Boolean + public fun C.isZero(): Boolean = this == constantZero /** * Check if the instant is NOT zero constant. */ @@ -200,7 +200,7 @@ public interface AbstractRationalFunctionalSpace, R: * Check if the instant is unit constant. */ @JvmName("constantIsOne") - public fun C.isOne(): Boolean + public fun C.isOne(): Boolean = this == constantOne /** * Check if the instant is NOT unit constant. */ @@ -210,12 +210,21 @@ public interface AbstractRationalFunctionalSpace, R: * Check if the instant is minus unit constant. */ @JvmName("constantIsMinusOne") - public fun C.isMinusOne(): Boolean + public fun C.isMinusOne(): Boolean = this == -constantOne /** * Check if the instant is NOT minus unit constant. */ @JvmName("constantIsNotMinusOne") public fun C.isNotMinusOne(): Boolean = !isMinusOne() + + /** + * 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 // endregion // region Constant-polynomial relation @@ -399,7 +408,7 @@ public interface AbstractRationalFunctionalSpace, R: /** * Check if the instant is zero rational function. */ - public fun R.isZero(): Boolean = this equalsTo zero + public fun R.isZero(): Boolean = numerator equalsTo polynomialZero /** * Check if the instant is NOT zero rational function. */ @@ -407,7 +416,7 @@ public interface AbstractRationalFunctionalSpace, R: /** * Check if the instant is unit rational function. */ - public fun R.isOne(): Boolean = this equalsTo one + public fun R.isOne(): Boolean = numerator equalsTo denominator /** * Check if the instant is NOT unit rational function. */ @@ -415,7 +424,7 @@ public interface AbstractRationalFunctionalSpace, R: /** * Check if the instant is minus unit rational function. */ - public fun R.isMinusOne(): Boolean = this equalsTo -one + public fun R.isMinusOne(): Boolean = (numerator + denominator).isZero() /** * Check if the instant is NOT minus unit rational function. */ @@ -597,35 +606,13 @@ public interface AbstractRationalFunctionalSpaceOverRing.cleanUp() = filterValues { it > 0U } //fun > Variable.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1U) to one)) // //context(LabeledPolynomialSpace) -//fun > Variable.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1U) to ring.one)) +//fun > Variable.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1U) to constantOne)) // //context(A) //fun > Variable.asLabeledPolynomial(c: C) : LabeledPolynomial = @@ -328,71 +333,54 @@ internal fun Map.cleanUp() = filterValues { it > 0U } */ @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE", "INAPPLICABLE_JVM_NAME") public class LabeledPolynomialSpace>( - public val ring: A, -) : AbstractPolynomialSpace> { - // region Constant-integer relation - @JvmName("constantIntPlus") - public override operator fun C.plus(other: Int): C = ring { optimizedAddMultiplied(this@plus, one, other) } - @JvmName("constantIntMinus") - public override operator fun C.minus(other: Int): C = ring { optimizedAddMultiplied(this@minus, one, -other) } - @JvmName("constantIntTimes") - public override operator fun C.times(other: Int): C = ring { optimizedMultiply(this@times, other) } - // endregion - - // region Integer-constant relation - @JvmName("intConstantPlus") - public override operator fun Int.plus(other: C): C = ring { optimizedAddMultiplied(other, one, this@plus) } - @JvmName("intConstantMinus") - public override operator fun Int.minus(other: C): C = ring { optimizedAddMultiplied(-other, one, this@minus) } - @JvmName("intConstantTimes") - public override operator fun Int.times(other: C): C = ring { optimizedMultiply(other, this@times) } - // endregion + public override val ring: A, +) : AbstractPolynomialSpaceOverRing, A> { // region Variable-integer relation public operator fun Variable.plus(other: Int): LabeledPolynomial = if (other == 0) LabeledPolynomial(mapOf( - mapOf(this@plus to 1U) to ring.one, + mapOf(this@plus to 1U) to constantOne, )) else LabeledPolynomial(mapOf( - mapOf(this@plus to 1U) to ring.one, - emptyMap() to ring.one * other, + mapOf(this@plus to 1U) to constantOne, + emptyMap() to constantOne * other, )) public operator fun Variable.minus(other: Int): LabeledPolynomial = if (other == 0) LabeledPolynomial(mapOf( - mapOf(this@minus to 1U) to -ring.one, + mapOf(this@minus to 1U) to -constantOne, )) else LabeledPolynomial(mapOf( - mapOf(this@minus to 1U) to -ring.one, - emptyMap() to ring.one * other, + mapOf(this@minus to 1U) to -constantOne, + emptyMap() to constantOne * other, )) public operator fun Variable.times(other: Int): LabeledPolynomial = if (other == 0) zero else LabeledPolynomial(mapOf( - mapOf(this to 1U) to ring.one * other, + mapOf(this to 1U) to constantOne * other, )) // endregion // region Integer-variable relation public operator fun Int.plus(other: Variable): LabeledPolynomial = if (this == 0) LabeledPolynomial(mapOf( - mapOf(other to 1U) to ring.one, + mapOf(other to 1U) to constantOne, )) else LabeledPolynomial(mapOf( - mapOf(other to 1U) to ring.one, - emptyMap() to ring.one * this@plus, + mapOf(other to 1U) to constantOne, + emptyMap() to constantOne * this@plus, )) public operator fun Int.minus(other: Variable): LabeledPolynomial = if (this == 0) LabeledPolynomial(mapOf( - mapOf(other to 1U) to -ring.one, + mapOf(other to 1U) to -constantOne, )) else LabeledPolynomial(mapOf( - mapOf(other to 1U) to -ring.one, - emptyMap() to ring.one * this@minus, + mapOf(other to 1U) to -constantOne, + emptyMap() to constantOne * this@minus, )) public operator fun Int.times(other: Variable): LabeledPolynomial = if (this == 0) zero else LabeledPolynomial(mapOf( - mapOf(other to 1U) to ring.one * this@times, + mapOf(other to 1U) to constantOne * this@times, )) // endregion @@ -406,7 +394,7 @@ public class LabeledPolynomialSpace>( .apply { val degs = emptyMap() - val result = getOrElse(degs) { ring.zero } + other + val result = getOrElse(degs) { constantZero } + other if (result.isZero()) remove(degs) else this[degs] = result @@ -421,7 +409,7 @@ public class LabeledPolynomialSpace>( .apply { val degs = emptyMap() - val result = getOrElse(degs) { ring.zero } - other + val result = getOrElse(degs) { constantZero } - other if (result.isZero()) remove(degs) else this[degs] = result @@ -447,7 +435,7 @@ public class LabeledPolynomialSpace>( .apply { val degs = emptyMap() - val result = this@plus + getOrElse(degs) { ring.zero } + val result = this@plus + getOrElse(degs) { constantZero } if (result.isZero()) remove(degs) else this[degs] = result @@ -462,7 +450,7 @@ public class LabeledPolynomialSpace>( .apply { val degs = emptyMap() - val result = this@minus - getOrElse(degs) { ring.zero } + val result = this@minus - getOrElse(degs) { constantZero } if (result.isZero()) remove(degs) else this[degs] = result @@ -478,44 +466,21 @@ public class LabeledPolynomialSpace>( ) // endregion - // region Constant-constant relation - @JvmName("constantUnaryMinus") - override operator fun C.unaryMinus(): C = ring { -this@unaryMinus } - @JvmName("constantPlus") - override operator fun C.plus(other: C): C = ring { this@plus + other } - @JvmName("constantMinus") - override operator fun C.minus(other: C): C = ring { this@minus - other } - @JvmName("constantTimes") - override operator fun C.times(other: C): C = ring { this@times * other } - @JvmName("constantIsZero") - public override fun C.isZero(): Boolean = ring { this == zero } - @JvmName("constantIsNotZero") - public override fun C.isNotZero(): Boolean = ring { this != zero } - @JvmName("constantIsOne") - public override fun C.isOne(): Boolean = ring { this == one } - @JvmName("constantIsNotOne") - public override fun C.isNotOne(): Boolean = ring { this != one } - @JvmName("constantIsMinusOne") - public override fun C.isMinusOne(): Boolean = ring { this == -one } - @JvmName("constantIsNotMinusOne") - public override fun C.isNotMinusOne(): Boolean = ring { this != -one } - // endregion - // region Constant-variable relation public operator fun C.plus(other: Variable): LabeledPolynomial = if (isZero()) LabeledPolynomial(mapOf( - mapOf(other to 1U) to ring.one, + mapOf(other to 1U) to constantOne, )) else LabeledPolynomial(mapOf( - mapOf(other to 1U) to ring.one, + mapOf(other to 1U) to constantOne, emptyMap() to this@plus, )) public operator fun C.minus(other: Variable): LabeledPolynomial = if (isZero()) LabeledPolynomial(mapOf( - mapOf(other to 1U) to -ring.one, + mapOf(other to 1U) to -constantOne, )) else LabeledPolynomial(mapOf( - mapOf(other to 1U) to -ring.one, + mapOf(other to 1U) to -constantOne, emptyMap() to this@minus, )) public operator fun C.times(other: Variable): LabeledPolynomial = @@ -528,18 +493,18 @@ public class LabeledPolynomialSpace>( // region Variable-constant relation public operator fun Variable.plus(other: C): LabeledPolynomial = if (other.isZero()) LabeledPolynomial(mapOf( - mapOf(this@plus to 1U) to ring.one, + mapOf(this@plus to 1U) to constantOne, )) else LabeledPolynomial(mapOf( - mapOf(this@plus to 1U) to ring.one, + mapOf(this@plus to 1U) to constantOne, emptyMap() to other, )) public operator fun Variable.minus(other: C): LabeledPolynomial = if (other.isZero()) LabeledPolynomial(mapOf( - mapOf(this@minus to 1U) to -ring.one, + mapOf(this@minus to 1U) to -constantOne, )) else LabeledPolynomial(mapOf( - mapOf(this@minus to 1U) to -ring.one, + mapOf(this@minus to 1U) to -constantOne, emptyMap() to other, )) public operator fun Variable.times(other: C): LabeledPolynomial = @@ -559,7 +524,7 @@ public class LabeledPolynomialSpace>( .apply { val degs = emptyMap() - val result = this@plus + getOrElse(degs) { ring.zero } + val result = this@plus + getOrElse(degs) { constantZero } if (result.isZero()) remove(degs) else this[degs] = result @@ -577,7 +542,7 @@ public class LabeledPolynomialSpace>( val degs = emptyMap() - val result = this@minus - getOrElse(degs) { ring.zero } + val result = this@minus - getOrElse(degs) { constantZero } if (result.isZero()) remove(degs) else this[degs] = result @@ -607,7 +572,7 @@ public class LabeledPolynomialSpace>( .apply { val degs = emptyMap() - val result = getOrElse(degs) { ring.zero } + other + val result = getOrElse(degs) { constantZero } + other if (result.isZero()) remove(degs) else this[degs] = result @@ -628,7 +593,7 @@ public class LabeledPolynomialSpace>( val degs = emptyMap() - val result = getOrElse(degs) { ring.zero } - other + val result = getOrElse(degs) { constantZero } - other if (result.isZero()) remove(degs) else this[degs] = result @@ -651,37 +616,37 @@ public class LabeledPolynomialSpace>( // region Variable-variable relation public operator fun Variable.plus(other: Variable): LabeledPolynomial = if (this == other) LabeledPolynomial(mapOf( - mapOf(this to 1U) to ring.one * 2 + mapOf(this to 1U) to constantOne * 2 )) else LabeledPolynomial(mapOf( - mapOf(this to 1U) to ring.one, - mapOf(other to 1U) to ring.one, + mapOf(this to 1U) to constantOne, + mapOf(other to 1U) to constantOne, )) public operator fun Variable.minus(other: Variable): LabeledPolynomial = if (this == other) zero else LabeledPolynomial(mapOf( - mapOf(this to 1U) to ring.one, - mapOf(other to 1U) to -ring.one, + mapOf(this to 1U) to constantOne, + mapOf(other to 1U) to -constantOne, )) public operator fun Variable.times(other: Variable): LabeledPolynomial = if (this == other) LabeledPolynomial(mapOf( - mapOf(this to 2U) to ring.one + mapOf(this to 2U) to constantOne )) else LabeledPolynomial(mapOf( - mapOf(this to 1U, other to 1U) to ring.one, + mapOf(this to 1U, other to 1U) to constantOne, )) // endregion // region Variable-polynomial relation public operator fun Variable.plus(other: LabeledPolynomial): LabeledPolynomial = with(other.coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(mapOf(this@plus to 1u) to ring.one)) + if (isEmpty()) LabeledPolynomial(mapOf(mapOf(this@plus to 1u) to constantOne)) else LabeledPolynomial( toMutableMap() .apply { val degs = mapOf(this@plus to 1U) - val result = ring.one + getOrElse(degs) { ring.zero } + val result = constantOne + getOrElse(degs) { constantZero } if (result.isZero()) remove(degs) else this[degs] = result @@ -690,7 +655,7 @@ public class LabeledPolynomialSpace>( } public operator fun Variable.minus(other: LabeledPolynomial): LabeledPolynomial = with(other.coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(mapOf(this@minus to 1u) to ring.one)) + if (isEmpty()) LabeledPolynomial(mapOf(mapOf(this@minus to 1u) to constantOne)) else LabeledPolynomial( toMutableMap() .apply { @@ -698,7 +663,7 @@ public class LabeledPolynomialSpace>( val degs = mapOf(this@minus to 1U) - val result = ring.one - getOrElse(degs) { ring.zero } + val result = constantOne - getOrElse(degs) { constantZero } if (result.isZero()) remove(degs) else this[degs] = result @@ -715,13 +680,13 @@ public class LabeledPolynomialSpace>( // region Polynomial-variable relation public operator fun LabeledPolynomial.plus(other: Variable): LabeledPolynomial = with(coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(mapOf(other to 1u) to ring.one)) + if (isEmpty()) LabeledPolynomial(mapOf(mapOf(other to 1u) to constantOne)) else LabeledPolynomial( toMutableMap() .apply { val degs = mapOf(other to 1U) - val result = ring.one + getOrElse(degs) { ring.zero } + val result = constantOne + getOrElse(degs) { constantZero } if (result.isZero()) remove(degs) else this[degs] = result @@ -730,13 +695,13 @@ public class LabeledPolynomialSpace>( } public operator fun LabeledPolynomial.minus(other: Variable): LabeledPolynomial = with(coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(mapOf(other to 1u) to ring.one)) + if (isEmpty()) LabeledPolynomial(mapOf(mapOf(other to 1u) to constantOne)) else LabeledPolynomial( toMutableMap() .apply { val degs = mapOf(other to 1U) - val result = ring.one - getOrElse(degs) { ring.zero } + val result = constantOne - getOrElse(degs) { constantZero } if (result.isZero()) remove(degs) else this[degs] = result @@ -799,8 +764,8 @@ public class LabeledPolynomialSpace>( ) } - override val zero: LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to ring.zero)) - override val one: LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to ring.one)) + override val zero: LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to constantZero)) + override val one: LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to constantOne)) // TODO: Docs @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") @@ -872,7 +837,7 @@ public class LabeledPolynomialSpace>( override fun LabeledPolynomial.asConstantOrNull(): C? = with(coefficients) { - if(isConstant()) getOrElse(emptyMap()) { ring.zero } + if(isConstant()) getOrElse(emptyMap()) { constantZero } else null } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt new file mode 100644 index 000000000..203c9e07c --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt @@ -0,0 +1,464 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.invoke + + +public class LabeledRationalFunction( + public override val numerator: LabeledPolynomial, + public override val denominator: LabeledPolynomial +) : AbstractRationalFunction> { + override fun toString(): String = "LabeledRationalFunction${numerator.coefficients}/${denominator.coefficients}" +} + +// region Internal utilities + +/** + * Represents internal [LabeledRationalFunction] errors. + */ +internal class LabeledRationalFunctionError : Error { + constructor(): super() + constructor(message: String): super(message) + constructor(message: String?, cause: Throwable?): super(message, cause) + constructor(cause: Throwable?): super(cause) +} + +/** + * Throws an [LabeledRationalFunctionError] with the given [message]. + */ +internal fun labeledRationalFunctionError(message: Any): Nothing = throw LabeledRationalFunctionError(message.toString()) + +// endregion + +// region Constructors and converters +// Waiting for context receivers :( TODO: Replace with context receivers when they will be available + +//context(RationalFunctionSpace) +//@Suppress("FunctionName") +//internal fun > RationalFunction(numerator: Polynomial, denominator: Polynomial): RationalFunction = +// if (denominator.isZero()) throw ArithmeticException("/ by zero") +// else RationalFunction(numerator, denominator) +//context(RationalFunctionSpace) +//@Suppress("FunctionName") +//public fun > RationalFunction(numeratorCoefficients: List, denominatorCoefficients: List, reverse: Boolean = false): RationalFunction = +// RationalFunction( +// Polynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), +// Polynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } ).also { if (it.isZero()) } +// ) +//context(RationalFunctionSpace) +//@Suppress("FunctionName") +//public fun > RationalFunction(numerator: Polynomial): RationalFunction = +// RationalFunction(numerator, onePolynomial) +//context(RationalFunctionSpace) +//@Suppress("FunctionName") +//public fun > RationalFunction(numeratorCoefficients: List, reverse: Boolean = false): RationalFunction = +// RationalFunction( +// Polynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ) +// ) + +// TODO: Rewrite former constructors as fabrics +//constructor(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>) : this( +//LabeledPolynomial(numeratorCoefficients), +//LabeledPolynomial(denominatorCoefficients) +//) +// +//constructor(numeratorCoefficients: Collection, C>>, denominatorCoefficients: Collection, C>>) : this( +//LabeledPolynomial(numeratorCoefficients), +//LabeledPolynomial(denominatorCoefficients) +//) +// +//constructor(numerator: LabeledPolynomial) : this(numerator, numerator.getOne()) +//constructor(numeratorCoefficients: Map, C>) : this( +//LabeledPolynomial(numeratorCoefficients) +//) +// +//constructor(numeratorCoefficients: Collection, C>>) : this( +//LabeledPolynomial(numeratorCoefficients) +//) + +// endregion + +public class LabeledRationalFunctionSpace>( + public val ring: A, +) : AbstractRationalFunctionalSpaceOverPolynomialSpace, LabeledRationalFunction, A> { + + override val polynomialRing : LabeledPolynomialSpace = LabeledPolynomialSpace(ring) + + // region Rational-integer relation + /** + * Returns sum of the rational function and the integer represented as rational function. + * + * The operation is equivalent to adding [other] copies of unit polynomial to [this]. + */ + public override operator fun LabeledRationalFunction.plus(other: Int): LabeledRationalFunction = + LabeledRationalFunction( + numerator + denominator * other, + denominator + ) + /** + * Returns difference between the rational function and the integer represented as rational function. + * + * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. + */ + public override operator fun LabeledRationalFunction.minus(other: Int): LabeledRationalFunction = + LabeledRationalFunction( + numerator - denominator * other, + denominator + ) + /** + * Returns product of the rational function and the integer represented as rational function. + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + public override operator fun LabeledRationalFunction.times(other: Int): LabeledRationalFunction = + LabeledRationalFunction( + numerator * other, + denominator + ) + // endregion + + // region Integer-Rational relation + /** + * Returns sum of the integer represented as 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: LabeledRationalFunction): LabeledRationalFunction = + LabeledRationalFunction( + other.denominator * this + other.numerator, + other.denominator + ) + /** + * Returns difference between the integer represented as 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: LabeledRationalFunction): LabeledRationalFunction = + LabeledRationalFunction( + other.denominator * this - other.numerator, + other.denominator + ) + /** + * Returns product of the integer represented as rational function and the rational function. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + public override operator fun Int.times(other: LabeledRationalFunction): LabeledRationalFunction = + LabeledRationalFunction( + this * other.numerator, + other.denominator + ) + // endregion + + // region Constant-rational relation + /** + * Returns sum of the constant represented as rational function and the rational function. + */ + public override operator fun C.plus(other: LabeledRationalFunction): LabeledRationalFunction = + LabeledRationalFunction( + other.denominator * this + other.numerator, + other.denominator + ) + /** + * Returns difference between the constant represented as polynomial and the rational function. + */ + public override operator fun C.minus(other: LabeledRationalFunction): LabeledRationalFunction = + LabeledRationalFunction( + other.denominator * this - other.numerator, + other.denominator + ) + /** + * Returns product of the constant represented as polynomial and the rational function. + */ + public override operator fun C.times(other: LabeledRationalFunction): LabeledRationalFunction = + LabeledRationalFunction( + this * other.numerator, + other.denominator + ) + // endregion + + // region Rational-constant relation + /** + * Returns sum of the constant represented as rational function and the rational function. + */ + public override operator fun LabeledRationalFunction.plus(other: C): LabeledRationalFunction = + LabeledRationalFunction( + numerator + denominator * other, + denominator + ) + /** + * Returns difference between the constant represented as rational function and the rational function. + */ + public override operator fun LabeledRationalFunction.minus(other: C): LabeledRationalFunction = + LabeledRationalFunction( + numerator - denominator * other, + denominator + ) + /** + * Returns product of the constant represented as rational function and the rational function. + */ + public override operator fun LabeledRationalFunction.times(other: C): LabeledRationalFunction = + LabeledRationalFunction( + numerator * other, + denominator + ) + // endregion + + // region Polynomial-rational relation + /** + * Returns sum of the polynomial represented as rational function and the rational function. + */ + public override operator fun LabeledPolynomial.plus(other: LabeledRationalFunction): LabeledRationalFunction = + LabeledRationalFunction( + other.denominator * this + other.numerator, + other.denominator + ) + /** + * Returns difference between the polynomial represented as polynomial and the rational function. + */ + public override operator fun LabeledPolynomial.minus(other: LabeledRationalFunction): LabeledRationalFunction = + LabeledRationalFunction( + other.denominator * this - other.numerator, + other.denominator + ) + /** + * Returns product of the polynomial represented as polynomial and the rational function. + */ + public override operator fun LabeledPolynomial.times(other: LabeledRationalFunction): LabeledRationalFunction = + LabeledRationalFunction( + this * other.numerator, + other.denominator + ) + // endregion + + // region Rational-polynomial relation + /** + * Returns sum of the polynomial represented as rational function and the rational function. + */ + public override operator fun LabeledRationalFunction.plus(other: LabeledPolynomial): LabeledRationalFunction = + LabeledRationalFunction( + numerator + denominator * other, + denominator + ) + /** + * Returns difference between the polynomial represented as rational function and the rational function. + */ + public override operator fun LabeledRationalFunction.minus(other: LabeledPolynomial): LabeledRationalFunction = + LabeledRationalFunction( + numerator - denominator * other, + denominator + ) + /** + * Returns product of the polynomial represented as rational function and the rational function. + */ + public override operator fun LabeledRationalFunction.times(other: LabeledPolynomial): LabeledRationalFunction = + LabeledRationalFunction( + numerator * other, + denominator + ) + // endregion + + // region Rational-rational relation + /** + * Returns negation of the rational function. + */ + public override operator fun LabeledRationalFunction.unaryMinus(): LabeledRationalFunction = LabeledRationalFunction(-numerator, denominator) + /** + * Returns sum of the rational functions. + */ + public override operator fun LabeledRationalFunction.plus(other: LabeledRationalFunction): LabeledRationalFunction = + LabeledRationalFunction( + numerator * other.denominator + denominator * other.numerator, + denominator * other.denominator + ) + /** + * Returns difference of the rational functions. + */ + public override operator fun LabeledRationalFunction.minus(other: LabeledRationalFunction): LabeledRationalFunction = + LabeledRationalFunction( + numerator * other.denominator - denominator * other.numerator, + denominator * other.denominator + ) + /** + * Returns product of the rational functions. + */ + public override operator fun LabeledRationalFunction.times(other: LabeledRationalFunction): LabeledRationalFunction = + LabeledRationalFunction( + numerator * other.numerator, + denominator * other.denominator + ) + + /** + * Instance of zero rational function (zero of the rational functions ring). + */ + public override val zero: LabeledRationalFunction = LabeledRationalFunction(polynomialZero, polynomialOne) + /** + * Instance of unit polynomial (unit of the rational functions ring). + */ + public override val one: LabeledRationalFunction = LabeledRationalFunction(polynomialOne, polynomialOne) + + /** + * Checks equality of the rational functions. + */ + @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") + public override infix fun LabeledRationalFunction.equalsTo(other: LabeledRationalFunction): Boolean { + if (this === other) return true + + if ( !(numerator.isZero() xor other.numerator.isZero()) ) return false + + val variables = this.variables union other.variables + val thisNumeratorDegrees = this.numerator.degrees + val thisDenominatorDegrees = this.denominator.degrees + val otherNumeratorDegrees = other.numerator.degrees + val otherDenominatorDegrees = other.denominator.degrees + for (variable in variables) + if ( + thisNumeratorDegrees.getOrElse(variable) { 0u } + otherDenominatorDegrees.getOrElse(variable) { 0u } + != thisDenominatorDegrees.getOrElse(variable) { 0u } + otherNumeratorDegrees.getOrElse(variable) { 0u } + ) return false + + return numerator * other.denominator equalsTo other.numerator * denominator + } + // endregion + + // region Polynomial properties + /** + * 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 LabeledPolynomial.degrees: Map get() = polynomialRing { degrees } + /** + * Set of all variables that appear in the polynomial in positive exponents. + */ + public val LabeledPolynomial.variables: Set get() = polynomialRing { variables } + /** + * Count of all variables that appear in the polynomial in positive exponents. + */ + public val LabeledPolynomial.countOfVariables: Int get() = polynomialRing { countOfVariables } + // endregion + + // region Rational properties + /** + * Count of all variables that appear in the polynomial in positive exponents. + */ + public val LabeledRationalFunction.variables: Set + get() = numerator.variables union denominator.variables + /** + * Count of all variables that appear in the polynomial in positive exponents. + */ + public val LabeledRationalFunction.countOfVariables: Int get() = variables.size + // endregion + + // region REST TODO: Разобрать + + public operator fun LabeledRationalFunction.div(other: LabeledRationalFunction): LabeledRationalFunction = + LabeledRationalFunction( + numerator * other.denominator, + denominator * other.numerator + ) + + public operator fun LabeledRationalFunction.div(other: LabeledPolynomial): LabeledRationalFunction = + LabeledRationalFunction( + numerator, + denominator * other + ) + + public operator fun LabeledRationalFunction.div(other: C): LabeledRationalFunction = + LabeledRationalFunction( + numerator, + denominator * other + ) + +// operator fun invoke(arg: Map): LabeledRationalFunction = +// LabeledRationalFunction( +// numerator(arg), +// denominator(arg) +// ) +// +// @JvmName("invokeLabeledPolynomial") +// operator fun invoke(arg: Map>): LabeledRationalFunction = +// LabeledRationalFunction( +// numerator(arg), +// denominator(arg) +// ) +// +// @JvmName("invokeLabeledRationalFunction") +// operator fun invoke(arg: Map>): LabeledRationalFunction { +// var num = numerator invokeRFTakeNumerator arg +// var den = denominator invokeRFTakeNumerator arg +// for (variable in variables) if (variable in arg) { +// val degreeDif = degrees[variable]!! +// if (degreeDif > 0) +// den = multiplyByPower(den, arg[variable]!!.denominator, degreeDif) +// else +// num = multiplyByPower(num, arg[variable]!!.denominator, -degreeDif) +// } +// return LabeledRationalFunction(num, den) +// } +// +// override fun toString(): String = toString(emptyMap()) +// +// fun toString(names: Map = emptyMap()): String = +// when (true) { +// numerator.isZero() -> "0" +// denominator.isOne() -> numerator.toString(names) +// else -> "${numerator.toStringWithBrackets(names)}/${denominator.toStringWithBrackets(names)}" +// } +// +// fun toString(namer: (Variable) -> String): String = +// when (true) { +// numerator.isZero() -> "0" +// denominator.isOne() -> numerator.toString(namer) +// else -> "${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)}" +// } +// +// fun toStringWithBrackets(names: Map = emptyMap()): String = +// when (true) { +// numerator.isZero() -> "0" +// denominator.isOne() -> numerator.toStringWithBrackets(names) +// else -> "(${numerator.toStringWithBrackets(names)}/${denominator.toStringWithBrackets(names)})" +// } +// +// fun toStringWithBrackets(namer: (Variable) -> String): String = +// when (true) { +// numerator.isZero() -> "0" +// denominator.isOne() -> numerator.toStringWithBrackets(namer) +// else -> "(${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)})" +// } +// +// fun toReversedString(names: Map = emptyMap()): String = +// when (true) { +// numerator.isZero() -> "0" +// denominator.isOne() -> numerator.toReversedString(names) +// else -> "${numerator.toReversedStringWithBrackets(names)}/${denominator.toReversedStringWithBrackets(names)}" +// } +// +// fun toReversedString(namer: (Variable) -> String): String = +// when (true) { +// numerator.isZero() -> "0" +// denominator.isOne() -> numerator.toReversedString(namer) +// else -> "${numerator.toReversedStringWithBrackets(namer)}/${denominator.toReversedStringWithBrackets(namer)}" +// } +// +// fun toReversedStringWithBrackets(names: Map = emptyMap()): String = +// when (true) { +// numerator.isZero() -> "0" +// denominator.isOne() -> numerator.toReversedStringWithBrackets(names) +// else -> "(${numerator.toReversedStringWithBrackets(names)}/${denominator.toReversedStringWithBrackets(names)})" +// } +// +// fun toReversedStringWithBrackets(namer: (Variable) -> String): String = +// when (true) { +// numerator.isZero() -> "0" +// denominator.isOne() -> numerator.toReversedStringWithBrackets(namer) +// else -> "(${numerator.toReversedStringWithBrackets(namer)}/${denominator.toReversedStringWithBrackets(namer)})" +// } +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index f11338161..39ca43945 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -1,3 +1,8 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + package space.kscience.kmath.functions import space.kscience.kmath.operations.* @@ -272,7 +277,7 @@ public open class NumberedPolynomialSpace>( .apply { val degs = emptyList() - val result = getOrElse(degs) { ring.zero } + other + val result = getOrElse(degs) { constantZero } + other if (result.isZero()) remove(degs) else this[degs] = result @@ -287,7 +292,7 @@ public open class NumberedPolynomialSpace>( .apply { val degs = emptyList() - val result = getOrElse(degs) { ring.zero } - other + val result = getOrElse(degs) { constantZero } - other if (result.isZero()) remove(degs) else this[degs] = result @@ -313,7 +318,7 @@ public open class NumberedPolynomialSpace>( .apply { val degs = emptyList() - val result = this@plus + getOrElse(degs) { ring.zero } + val result = this@plus + getOrElse(degs) { constantZero } if (result.isZero()) remove(degs) else this[degs] = result @@ -328,7 +333,7 @@ public open class NumberedPolynomialSpace>( .apply { val degs = emptyList() - val result = this@minus - getOrElse(degs) { ring.zero } + val result = this@minus - getOrElse(degs) { constantZero } if (result.isZero()) remove(degs) else this[degs] = result @@ -354,7 +359,7 @@ public open class NumberedPolynomialSpace>( .apply { val degs = emptyList() - val result = this@plus + getOrElse(degs) { ring.zero } + val result = this@plus + getOrElse(degs) { constantZero } if (result.isZero()) remove(degs) else this[degs] = result @@ -372,7 +377,7 @@ public open class NumberedPolynomialSpace>( val degs = emptyList() - val result = this@minus - getOrElse(degs) { ring.zero } + val result = this@minus - getOrElse(degs) { constantZero } if (result.isZero()) remove(degs) else this[degs] = result @@ -402,7 +407,7 @@ public open class NumberedPolynomialSpace>( .apply { val degs = emptyList() - val result = getOrElse(degs) { ring.zero } + other + val result = getOrElse(degs) { constantZero } + other if (result.isZero()) remove(degs) else this[degs] = result @@ -421,7 +426,7 @@ public open class NumberedPolynomialSpace>( .apply { val degs = emptyList() - val result = getOrElse(degs) { ring.zero } - other + val result = getOrElse(degs) { constantZero } - other if (result.isZero()) remove(degs) else this[degs] = result @@ -522,7 +527,7 @@ public open class NumberedPolynomialSpace>( override val one: NumberedPolynomial = NumberedPolynomial( mapOf( - listOf() to ring.one // 1 * x_1^0 * x_2^0 * ... + listOf() to constantOne // 1 * x_1^0 * x_2^0 * ... ) ) @@ -538,6 +543,7 @@ public open class NumberedPolynomialSpace>( // Not sure is it necessary... // region Polynomial properties + // TODO: Replace `countOfVariables` with `lastVariable` and create new `countOfVariables` /** * Count of all variables that appear in the polynomial in positive exponents. */ @@ -590,7 +596,7 @@ public open class NumberedPolynomialSpace>( override fun NumberedPolynomial.asConstantOrNull(): C? = with(coefficients) { - if(isConstant()) getOrElse(emptyList()) { ring.zero } + if(isConstant()) getOrElse(emptyList()) { constantZero } else null } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt new file mode 100644 index 000000000..aff18d1f4 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt @@ -0,0 +1,453 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.* +import kotlin.math.max + + +public class NumberedRationalFunction internal constructor( + public override val numerator: NumberedPolynomial, + public override val denominator: NumberedPolynomial +) : AbstractRationalFunction> { + override fun toString(): String = "NumberedRationalFunction${numerator.coefficients}/${denominator.coefficients}" +} + +// region Internal utilities + +/** + * Represents internal [NumberedRationalFunction] errors. + */ +internal class NumberedRationalFunctionError : Error { + constructor(): super() + constructor(message: String): super(message) + constructor(message: String?, cause: Throwable?): super(message, cause) + constructor(cause: Throwable?): super(cause) +} + +/** + * Throws an [NumberedRationalFunctionError] with the given [message]. + */ +internal fun numberedRationalFunctionError(message: Any): Nothing = throw NumberedRationalFunctionError(message.toString()) + +// endregion + +// region Constructors and converters +// Waiting for context receivers :( TODO: Replace with context receivers when they will be available + +//context(RationalFunctionSpace) +//@Suppress("FunctionName") +//internal fun > RationalFunction(numerator: Polynomial, denominator: Polynomial): RationalFunction = +// if (denominator.isZero()) throw ArithmeticException("/ by zero") +// else RationalFunction(numerator, denominator) +//context(RationalFunctionSpace) +//@Suppress("FunctionName") +//public fun > RationalFunction(numeratorCoefficients: List, denominatorCoefficients: List, reverse: Boolean = false): RationalFunction = +// RationalFunction( +// Polynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), +// Polynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } ).also { if (it.isZero()) } +// ) +//context(RationalFunctionSpace) +//@Suppress("FunctionName") +//public fun > RationalFunction(numerator: Polynomial): RationalFunction = +// RationalFunction(numerator, onePolynomial) +//context(RationalFunctionSpace) +//@Suppress("FunctionName") +//public fun > RationalFunction(numeratorCoefficients: List, reverse: Boolean = false): RationalFunction = +// RationalFunction( +// Polynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ) +// ) + +// TODO: Rewrite former constructors as fabrics +//constructor(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>) : this( +//Polynomial(numeratorCoefficients), +//Polynomial(denominatorCoefficients) +//) +//constructor(numeratorCoefficients: Collection, C>>, denominatorCoefficients: Collection, C>>) : this( +//Polynomial(numeratorCoefficients), +//Polynomial(denominatorCoefficients) +//) +//constructor(numerator: Polynomial) : this(numerator, numerator.getOne()) +//constructor(numeratorCoefficients: Map, C>) : this( +//Polynomial(numeratorCoefficients) +//) +//constructor(numeratorCoefficients: Collection, C>>) : this( +//Polynomial(numeratorCoefficients) +//) + +// endregion + +public class NumberedRationalFunctionSpace> ( + public val ring: A, +) : AbstractRationalFunctionalSpaceOverPolynomialSpace, NumberedRationalFunction, A> { + + override val polynomialRing : NumberedPolynomialSpace = NumberedPolynomialSpace(ring) + + // region Rational-integer relation + /** + * Returns sum of the rational function and the integer represented as rational function. + * + * The operation is equivalent to adding [other] copies of unit polynomial to [this]. + */ + public override operator fun NumberedRationalFunction.plus(other: Int): NumberedRationalFunction = + NumberedRationalFunction( + numerator + denominator * other, + denominator + ) + /** + * Returns difference between the rational function and the integer represented as rational function. + * + * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. + */ + public override operator fun NumberedRationalFunction.minus(other: Int): NumberedRationalFunction = + NumberedRationalFunction( + numerator - denominator * other, + denominator + ) + /** + * Returns product of the rational function and the integer represented as rational function. + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + public override operator fun NumberedRationalFunction.times(other: Int): NumberedRationalFunction = + NumberedRationalFunction( + numerator * other, + denominator + ) + // endregion + + // region Integer-Rational relation + /** + * Returns sum of the integer represented as 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: NumberedRationalFunction): NumberedRationalFunction = + NumberedRationalFunction( + other.denominator * this + other.numerator, + other.denominator + ) + /** + * Returns difference between the integer represented as 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: NumberedRationalFunction): NumberedRationalFunction = + NumberedRationalFunction( + other.denominator * this - other.numerator, + other.denominator + ) + /** + * Returns product of the integer represented as rational function and the rational function. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + public override operator fun Int.times(other: NumberedRationalFunction): NumberedRationalFunction = + NumberedRationalFunction( + this * other.numerator, + other.denominator + ) + // endregion + + // region Constant-rational relation + /** + * Returns sum of the constant represented as rational function and the rational function. + */ + public override operator fun C.plus(other: NumberedRationalFunction): NumberedRationalFunction = + NumberedRationalFunction( + other.denominator * this + other.numerator, + other.denominator + ) + /** + * Returns difference between the constant represented as polynomial and the rational function. + */ + public override operator fun C.minus(other: NumberedRationalFunction): NumberedRationalFunction = + NumberedRationalFunction( + other.denominator * this - other.numerator, + other.denominator + ) + /** + * Returns product of the constant represented as polynomial and the rational function. + */ + public override operator fun C.times(other: NumberedRationalFunction): NumberedRationalFunction = + NumberedRationalFunction( + this * other.numerator, + other.denominator + ) + // endregion + + // region Rational-constant relation + /** + * Returns sum of the constant represented as rational function and the rational function. + */ + public override operator fun NumberedRationalFunction.plus(other: C): NumberedRationalFunction = + NumberedRationalFunction( + numerator + denominator * other, + denominator + ) + /** + * Returns difference between the constant represented as rational function and the rational function. + */ + public override operator fun NumberedRationalFunction.minus(other: C): NumberedRationalFunction = + NumberedRationalFunction( + numerator - denominator * other, + denominator + ) + /** + * Returns product of the constant represented as rational function and the rational function. + */ + public override operator fun NumberedRationalFunction.times(other: C): NumberedRationalFunction = + NumberedRationalFunction( + numerator * other, + denominator + ) + // endregion + + // region Polynomial-rational relation + /** + * Returns sum of the polynomial represented as rational function and the rational function. + */ + public override operator fun NumberedPolynomial.plus(other: NumberedRationalFunction): NumberedRationalFunction = + NumberedRationalFunction( + other.denominator * this + other.numerator, + other.denominator + ) + /** + * Returns difference between the polynomial represented as polynomial and the rational function. + */ + public override operator fun NumberedPolynomial.minus(other: NumberedRationalFunction): NumberedRationalFunction = + NumberedRationalFunction( + other.denominator * this - other.numerator, + other.denominator + ) + /** + * Returns product of the polynomial represented as polynomial and the rational function. + */ + public override operator fun NumberedPolynomial.times(other: NumberedRationalFunction): NumberedRationalFunction = + NumberedRationalFunction( + this * other.numerator, + other.denominator + ) + // endregion + + // region Rational-polynomial relation + /** + * Returns sum of the polynomial represented as rational function and the rational function. + */ + public override operator fun NumberedRationalFunction.plus(other: NumberedPolynomial): NumberedRationalFunction = + NumberedRationalFunction( + numerator + denominator * other, + denominator + ) + /** + * Returns difference between the polynomial represented as rational function and the rational function. + */ + public override operator fun NumberedRationalFunction.minus(other: NumberedPolynomial): NumberedRationalFunction = + NumberedRationalFunction( + numerator - denominator * other, + denominator + ) + /** + * Returns product of the polynomial represented as rational function and the rational function. + */ + public override operator fun NumberedRationalFunction.times(other: NumberedPolynomial): NumberedRationalFunction = + NumberedRationalFunction( + numerator * other, + denominator + ) + // endregion + + // region Rational-rational relation + /** + * Returns negation of the rational function. + */ + public override operator fun NumberedRationalFunction.unaryMinus(): NumberedRationalFunction = NumberedRationalFunction(-numerator, denominator) + /** + * Returns sum of the rational functions. + */ + public override operator fun NumberedRationalFunction.plus(other: NumberedRationalFunction): NumberedRationalFunction = + NumberedRationalFunction( + numerator * other.denominator + denominator * other.numerator, + denominator * other.denominator + ) + /** + * Returns difference of the rational functions. + */ + public override operator fun NumberedRationalFunction.minus(other: NumberedRationalFunction): NumberedRationalFunction = + NumberedRationalFunction( + numerator * other.denominator - denominator * other.numerator, + denominator * other.denominator + ) + /** + * Returns product of the rational functions. + */ + public override operator fun NumberedRationalFunction.times(other: NumberedRationalFunction): NumberedRationalFunction = + NumberedRationalFunction( + numerator * other.numerator, + denominator * other.denominator + ) + + /** + * Instance of zero rational function (zero of the rational functions ring). + */ + public override val zero: NumberedRationalFunction = NumberedRationalFunction(polynomialZero, polynomialOne) + /** + * Instance of unit polynomial (unit of the rational functions ring). + */ + public override val one: NumberedRationalFunction = NumberedRationalFunction(polynomialOne, polynomialOne) + + /** + * Checks equality of the rational functions. + */ + @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") + public override infix fun NumberedRationalFunction.equalsTo(other: NumberedRationalFunction): Boolean { + if (this === other) return true + + if ( !(numerator.isZero() xor other.numerator.isZero()) ) return false + + val countOfVariables = max(this.countOfVariables, other.countOfVariables) + val thisNumeratorDegrees = this.numerator.degrees + val thisDenominatorDegrees = this.denominator.degrees + val otherNumeratorDegrees = other.numerator.degrees + val otherDenominatorDegrees = other.denominator.degrees + for (variable in 0 until countOfVariables) + if ( + thisNumeratorDegrees.getOrElse(variable) { 0u } + otherDenominatorDegrees.getOrElse(variable) { 0u } + != thisDenominatorDegrees.getOrElse(variable) { 0u } + otherNumeratorDegrees.getOrElse(variable) { 0u } + ) return false + + return numerator * other.denominator equalsTo other.numerator * denominator + } + // endregion + + // region Polynomial properties + /** + * Count of all variables that appear in the polynomial in positive exponents. + */ + public val NumberedPolynomial.countOfVariables: Int get() = polynomialRing { countOfVariables } + /** + * 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 size of the list is [countOfVariables]. + */ + public val NumberedPolynomial.degrees: List get() = polynomialRing { degrees } + // endregion + + // region Rational properties + /** + * Count of all variables that appear in the polynomial in positive exponents. + */ + public val NumberedRationalFunction.countOfVariables: Int + get() = polynomialRing { max(numerator.countOfVariables, denominator.countOfVariables) } + // endregion + + // region REST TODO: Разобрать + + public operator fun NumberedRationalFunction.div(other: NumberedRationalFunction): NumberedRationalFunction = + NumberedRationalFunction( + numerator * other.denominator, + denominator * other.numerator + ) + + public operator fun NumberedRationalFunction.div(other: NumberedPolynomial): NumberedRationalFunction = + NumberedRationalFunction( + numerator, + denominator * other + ) + + public operator fun NumberedRationalFunction.div(other: C): NumberedRationalFunction = + NumberedRationalFunction( + numerator, + denominator * other + ) + +// operator fun invoke(arg: Map): NumberedRationalFunction = +// NumberedRationalFunction( +// numerator(arg), +// denominator(arg) +// ) +// +// @JvmName("invokePolynomial") +// operator fun invoke(arg: Map>): NumberedRationalFunction = +// NumberedRationalFunction( +// numerator(arg), +// denominator(arg) +// ) +// +// @JvmName("invokeRationalFunction") +// operator fun invoke(arg: Map>): NumberedRationalFunction { +// var num = numerator invokeRFTakeNumerator arg +// var den = denominator invokeRFTakeNumerator arg +// for (variable in 0 until max(numerator.countOfVariables, denominator.countOfVariables)) if (variable in arg) { +// val degreeDif = numerator.degrees.getOrElse(variable) { 0 } - denominator.degrees.getOrElse(variable) { 0 } +// if (degreeDif > 0) +// den = multiplyByPower(den, arg[variable]!!.denominator, degreeDif) +// else +// num = multiplyByPower(num, arg[variable]!!.denominator, -degreeDif) +// } +// return NumberedRationalFunction(num, den) +// } +// +// override fun toString(): String = toString(Polynomial.variableName) +// +// fun toString(withVariableName: String = Polynomial.variableName): String = +// when(true) { +// numerator.isZero() -> "0" +// denominator.isOne() -> numerator.toString(withVariableName) +// else -> "${numerator.toStringWithBrackets(withVariableName)}/${denominator.toStringWithBrackets(withVariableName)}" +// } +// +// fun toString(namer: (Int) -> String): String = +// when(true) { +// numerator.isZero() -> "0" +// denominator.isOne() -> numerator.toString(namer) +// else -> "${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)}" +// } +// +// fun toStringWithBrackets(withVariableName: String = Polynomial.variableName): String = +// when(true) { +// numerator.isZero() -> "0" +// denominator.isOne() -> numerator.toStringWithBrackets(withVariableName) +// else -> "(${numerator.toStringWithBrackets(withVariableName)}/${denominator.toStringWithBrackets(withVariableName)})" +// } +// +// fun toStringWithBrackets(namer: (Int) -> String): String = +// when(true) { +// numerator.isZero() -> "0" +// denominator.isOne() -> numerator.toStringWithBrackets(namer) +// else -> "(${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)})" +// } +// +// fun toReversedString(withVariableName: String = Polynomial.variableName): String = +// when(true) { +// numerator.isZero() -> "0" +// denominator.isOne() -> numerator.toReversedString(withVariableName) +// else -> "${numerator.toReversedStringWithBrackets(withVariableName)}/${denominator.toReversedStringWithBrackets(withVariableName)}" +// } +// +// fun toReversedString(namer: (Int) -> String): String = +// when(true) { +// numerator.isZero() -> "0" +// denominator.isOne() -> numerator.toReversedString(namer) +// else -> "${numerator.toReversedStringWithBrackets(namer)}/${denominator.toReversedStringWithBrackets(namer)}" +// } +// +// fun toReversedStringWithBrackets(withVariableName: String = Polynomial.variableName): String = +// when(true) { +// numerator.isZero() -> "0" +// denominator.isOne() -> numerator.toReversedStringWithBrackets(withVariableName) +// else -> "(${numerator.toReversedStringWithBrackets(withVariableName)}/${denominator.toReversedStringWithBrackets(withVariableName)})" +// } +// +// fun toReversedStringWithBrackets(namer: (Int) -> String): String = +// when(true) { +// numerator.isZero() -> "0" +// denominator.isOne() -> numerator.toReversedStringWithBrackets(namer) +// else -> "(${numerator.toReversedStringWithBrackets(namer)}/${denominator.toReversedStringWithBrackets(namer)})" +// } +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 2c764f4f5..1a324f72c 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -80,7 +80,7 @@ public open class PolynomialSpace>( coefficients .toMutableList() .apply { - val result = getOrElse(0) { ring.zero } + other + val result = getOrElse(0) { constantZero } + other val isResultZero = result.isZero() when { @@ -97,7 +97,7 @@ public open class PolynomialSpace>( coefficients .toMutableList() .apply { - val result = getOrElse(0) { ring.zero } - other + val result = getOrElse(0) { constantZero } - other val isResultZero = result.isZero() when { @@ -124,7 +124,7 @@ public open class PolynomialSpace>( other.coefficients .toMutableList() .apply { - val result = this@plus + getOrElse(0) { ring.zero } + val result = this@plus + getOrElse(0) { constantZero } val isResultZero = result.isZero() when { @@ -143,7 +143,7 @@ public open class PolynomialSpace>( .apply { forEachIndexed { index, c -> if (index != 0) this[index] = -c } - val result = this@minus - getOrElse(0) { ring.zero } + val result = this@minus - getOrElse(0) { constantZero } val isResultZero = result.isZero() when { @@ -281,7 +281,7 @@ public open class PolynomialSpace>( else -> coefficients[it] + other.coefficients[it] } } - .ifEmpty { listOf(ring.zero) } + .ifEmpty { listOf(constantZero) } ) public override operator fun Polynomial.minus(other: Polynomial): Polynomial = Polynomial( @@ -293,7 +293,7 @@ public open class PolynomialSpace>( else -> coefficients[it] - other.coefficients[it] } } - .ifEmpty { listOf(ring.zero) } + .ifEmpty { listOf(constantZero) } ) public override operator fun Polynomial.times(other: Polynomial): Polynomial { val thisDegree = degree @@ -321,7 +321,7 @@ public open class PolynomialSpace>( with(coefficients) { isNotEmpty() && asSequence().withIndex().any { (index, c) -> if (index == 0) c.isMinusOne() else c.isZero() } } // TODO: It's better to write new methods like `anyIndexed`. But what's better way to do it? override val zero: Polynomial = Polynomial(emptyList()) - override val one: Polynomial = Polynomial(listOf(ring.one)) + override val one: Polynomial = Polynomial(listOf(constantZero)) @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") public override infix fun Polynomial.equalsTo(other: Polynomial): Boolean = @@ -337,12 +337,12 @@ public open class PolynomialSpace>( // region Polynomial properties - public override val Polynomial.degree: Int get() = coefficients.indexOfLast { it != ring.zero } + public override val Polynomial.degree: Int get() = coefficients.indexOfLast { it != constantZero } public override fun Polynomial.asConstantOrNull(): C? = with(coefficients) { when { - isEmpty() -> ring.zero + isEmpty() -> constantZero degree > 0 -> null else -> first() } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index 78ca556db..e9916b634 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -1,3 +1,8 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + package space.kscience.kmath.functions import space.kscience.kmath.operations.* @@ -270,19 +275,6 @@ public class RationalFunctionSpace> ( denominator * other.denominator ) - /** - * Check if the instant is zero rational function. - */ - public override fun RationalFunction.isZero(): Boolean = numerator.isZero() - /** - * Check if the instant is unit rational function. - */ - public override fun RationalFunction.isOne(): Boolean = numerator.equalsTo(denominator) - /** - * Check if the instant is minus unit rational function. - */ - public override fun RationalFunction.isMinusOne(): Boolean = (numerator + denominator).isZero() - /** * Instance of zero rational function (zero of the rational functions ring). */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt index 62ac31b64..9cf4f2652 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt @@ -1,3 +1,8 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + package space.kscience.kmath.functions import space.kscience.kmath.operations.* @@ -30,7 +35,7 @@ import kotlin.contracts.* //fun > power(arg: Variable, pow: UInt): LabeledPolynomial = // if (pow == 0U) one // else LabeledPolynomial(mapOf( -// mapOf(arg to pow) to ring.one +// mapOf(arg to pow) to constantOne // )) // //// endregion diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt new file mode 100644 index 000000000..26e8ab17a --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt @@ -0,0 +1,130 @@ +package math.polynomials + +import math.ringsAndFields.* +import space.kscience.kmath.functions.LabeledRationalFunction + + +fun > T.toLabeledRationalFunction() = LabeledRationalFunction(this.toLabeledPolynomial()) + +// region Operator extensions + +// region Field case + +fun > LabeledRationalFunction.reduced(): LabeledRationalFunction { + val greatestCommonDivider = polynomialGCD(numerator, denominator) + return LabeledRationalFunction( + numerator / greatestCommonDivider, + denominator / greatestCommonDivider + ) +} + +// endregion + +// region Constants + +operator fun > T.plus(other: LabeledRationalFunction) = other + this +operator fun > Integer.plus(other: LabeledRationalFunction) = other + this +operator fun > Int.plus(other: LabeledRationalFunction) = other + this +operator fun > Long.plus(other: LabeledRationalFunction) = other + this + +operator fun > T.minus(other: LabeledRationalFunction) = -other + this +operator fun > Integer.minus(other: LabeledRationalFunction) = -other + this +operator fun > Int.minus(other: LabeledRationalFunction) = -other + this +operator fun > Long.minus(other: LabeledRationalFunction) = -other + this + +operator fun > T.times(other: LabeledRationalFunction) = other * this +operator fun > Integer.times(other: LabeledRationalFunction) = other * this +operator fun > Int.times(other: LabeledRationalFunction) = other * this +operator fun > Long.times(other: LabeledRationalFunction) = other * this + +// endregion + +// region Polynomials + +operator fun > LabeledRationalFunction.plus(other: UnivariatePolynomial) = + LabeledRationalFunction( + numerator + denominator * other.toLabeledPolynomial(), + denominator + ) +operator fun > LabeledRationalFunction.plus(other: UnivariateRationalFunction) = + LabeledRationalFunction( + numerator * other.denominator.toLabeledPolynomial() + denominator * other.numerator.toLabeledPolynomial(), + denominator * other.denominator.toLabeledPolynomial() + ) +operator fun > LabeledRationalFunction.plus(other: Polynomial) = + LabeledRationalFunction( + numerator + denominator * other.toLabeledPolynomial(), + denominator + ) +operator fun > LabeledRationalFunction.plus(other: NumberedRationalFunction) = + LabeledRationalFunction( + numerator * other.denominator.toLabeledPolynomial() + denominator * other.numerator.toLabeledPolynomial(), + denominator * other.denominator.toLabeledPolynomial() + ) + +operator fun > LabeledRationalFunction.minus(other: UnivariatePolynomial) = + LabeledRationalFunction( + numerator - denominator * other.toLabeledPolynomial(), + denominator + ) +operator fun > LabeledRationalFunction.minus(other: UnivariateRationalFunction) = + LabeledRationalFunction( + numerator * other.denominator.toLabeledPolynomial() - denominator * other.numerator.toLabeledPolynomial(), + denominator * other.denominator.toLabeledPolynomial() + ) +operator fun > LabeledRationalFunction.minus(other: Polynomial) = + LabeledRationalFunction( + numerator - denominator * other.toLabeledPolynomial(), + denominator + ) +operator fun > LabeledRationalFunction.minus(other: NumberedRationalFunction) = + LabeledRationalFunction( + numerator * other.denominator.toLabeledPolynomial() - denominator * other.numerator.toLabeledPolynomial(), + denominator * other.denominator.toLabeledPolynomial() + ) + +operator fun > LabeledRationalFunction.times(other: UnivariatePolynomial) = + LabeledRationalFunction( + numerator * other.toLabeledPolynomial(), + denominator + ) +operator fun > LabeledRationalFunction.times(other: UnivariateRationalFunction) = + LabeledRationalFunction( + numerator * other.numerator.toLabeledPolynomial(), + denominator * other.denominator.toLabeledPolynomial() + ) +operator fun > LabeledRationalFunction.times(other: Polynomial) = + LabeledRationalFunction( + numerator * other.toLabeledPolynomial(), + denominator + ) +operator fun > LabeledRationalFunction.times(other: NumberedRationalFunction) = + LabeledRationalFunction( + numerator * other.numerator.toLabeledPolynomial(), + denominator * other.denominator.toLabeledPolynomial() + ) + +operator fun > LabeledRationalFunction.div(other: UnivariatePolynomial) = + LabeledRationalFunction( + numerator, + denominator * other.toLabeledPolynomial() + ) +operator fun > LabeledRationalFunction.div(other: UnivariateRationalFunction) = + LabeledRationalFunction( + numerator * other.denominator.toLabeledPolynomial(), + denominator * other.numerator.toLabeledPolynomial() + ) +operator fun > LabeledRationalFunction.div(other: Polynomial) = + LabeledRationalFunction( + numerator, + denominator * other.toLabeledPolynomial() + ) +operator fun > LabeledRationalFunction.div(other: NumberedRationalFunction) = + LabeledRationalFunction( + numerator * other.denominator.toLabeledPolynomial(), + denominator * other.numerator.toLabeledPolynomial() + ) + +// endregion + +// endregion \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt new file mode 100644 index 000000000..7c8120c68 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + + +//// region Operator extensions +// +//// region Field case +// +//fun > NumberedRationalFunction.reduced(): NumberedRationalFunction { +// val greatestCommonDivider = polynomialGCD(numerator, denominator) +// return NumberedRationalFunction( +// numerator / greatestCommonDivider, +// denominator / greatestCommonDivider +// ) +//} +// +//// endregion +// +//// endregion \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/rationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/rationalFunctionUtil.kt index 9147bc023..d5bbc3b82 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/rationalFunctionUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/rationalFunctionUtil.kt @@ -1,3 +1,8 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + package space.kscience.kmath.functions -- 2.34.1 From 44febbdd730451bb7a941f1bcc973b661bd5d63b Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Mon, 14 Mar 2022 20:19:42 +0300 Subject: [PATCH 021/275] Processed labeledRationalFunctionUtil.kt --- .../kscience/kmath/functions/Polynomial.kt | 1 - .../functions/labeledRationalFunctionUtil.kt | 147 +++--------------- 2 files changed, 20 insertions(+), 128 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 1a324f72c..49184468b 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -6,7 +6,6 @@ package space.kscience.kmath.functions import space.kscience.kmath.operations.* -import kotlin.jvm.JvmName import kotlin.math.max import kotlin.math.min diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt index 26e8ab17a..575dfed48 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt @@ -1,130 +1,23 @@ -package math.polynomials +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ -import math.ringsAndFields.* -import space.kscience.kmath.functions.LabeledRationalFunction +package space.kscience.kmath.functions -fun > T.toLabeledRationalFunction() = LabeledRationalFunction(this.toLabeledPolynomial()) - -// region Operator extensions - -// region Field case - -fun > LabeledRationalFunction.reduced(): LabeledRationalFunction { - val greatestCommonDivider = polynomialGCD(numerator, denominator) - return LabeledRationalFunction( - numerator / greatestCommonDivider, - denominator / greatestCommonDivider - ) -} - -// endregion - -// region Constants - -operator fun > T.plus(other: LabeledRationalFunction) = other + this -operator fun > Integer.plus(other: LabeledRationalFunction) = other + this -operator fun > Int.plus(other: LabeledRationalFunction) = other + this -operator fun > Long.plus(other: LabeledRationalFunction) = other + this - -operator fun > T.minus(other: LabeledRationalFunction) = -other + this -operator fun > Integer.minus(other: LabeledRationalFunction) = -other + this -operator fun > Int.minus(other: LabeledRationalFunction) = -other + this -operator fun > Long.minus(other: LabeledRationalFunction) = -other + this - -operator fun > T.times(other: LabeledRationalFunction) = other * this -operator fun > Integer.times(other: LabeledRationalFunction) = other * this -operator fun > Int.times(other: LabeledRationalFunction) = other * this -operator fun > Long.times(other: LabeledRationalFunction) = other * this - -// endregion - -// region Polynomials - -operator fun > LabeledRationalFunction.plus(other: UnivariatePolynomial) = - LabeledRationalFunction( - numerator + denominator * other.toLabeledPolynomial(), - denominator - ) -operator fun > LabeledRationalFunction.plus(other: UnivariateRationalFunction) = - LabeledRationalFunction( - numerator * other.denominator.toLabeledPolynomial() + denominator * other.numerator.toLabeledPolynomial(), - denominator * other.denominator.toLabeledPolynomial() - ) -operator fun > LabeledRationalFunction.plus(other: Polynomial) = - LabeledRationalFunction( - numerator + denominator * other.toLabeledPolynomial(), - denominator - ) -operator fun > LabeledRationalFunction.plus(other: NumberedRationalFunction) = - LabeledRationalFunction( - numerator * other.denominator.toLabeledPolynomial() + denominator * other.numerator.toLabeledPolynomial(), - denominator * other.denominator.toLabeledPolynomial() - ) - -operator fun > LabeledRationalFunction.minus(other: UnivariatePolynomial) = - LabeledRationalFunction( - numerator - denominator * other.toLabeledPolynomial(), - denominator - ) -operator fun > LabeledRationalFunction.minus(other: UnivariateRationalFunction) = - LabeledRationalFunction( - numerator * other.denominator.toLabeledPolynomial() - denominator * other.numerator.toLabeledPolynomial(), - denominator * other.denominator.toLabeledPolynomial() - ) -operator fun > LabeledRationalFunction.minus(other: Polynomial) = - LabeledRationalFunction( - numerator - denominator * other.toLabeledPolynomial(), - denominator - ) -operator fun > LabeledRationalFunction.minus(other: NumberedRationalFunction) = - LabeledRationalFunction( - numerator * other.denominator.toLabeledPolynomial() - denominator * other.numerator.toLabeledPolynomial(), - denominator * other.denominator.toLabeledPolynomial() - ) - -operator fun > LabeledRationalFunction.times(other: UnivariatePolynomial) = - LabeledRationalFunction( - numerator * other.toLabeledPolynomial(), - denominator - ) -operator fun > LabeledRationalFunction.times(other: UnivariateRationalFunction) = - LabeledRationalFunction( - numerator * other.numerator.toLabeledPolynomial(), - denominator * other.denominator.toLabeledPolynomial() - ) -operator fun > LabeledRationalFunction.times(other: Polynomial) = - LabeledRationalFunction( - numerator * other.toLabeledPolynomial(), - denominator - ) -operator fun > LabeledRationalFunction.times(other: NumberedRationalFunction) = - LabeledRationalFunction( - numerator * other.numerator.toLabeledPolynomial(), - denominator * other.denominator.toLabeledPolynomial() - ) - -operator fun > LabeledRationalFunction.div(other: UnivariatePolynomial) = - LabeledRationalFunction( - numerator, - denominator * other.toLabeledPolynomial() - ) -operator fun > LabeledRationalFunction.div(other: UnivariateRationalFunction) = - LabeledRationalFunction( - numerator * other.denominator.toLabeledPolynomial(), - denominator * other.numerator.toLabeledPolynomial() - ) -operator fun > LabeledRationalFunction.div(other: Polynomial) = - LabeledRationalFunction( - numerator, - denominator * other.toLabeledPolynomial() - ) -operator fun > LabeledRationalFunction.div(other: NumberedRationalFunction) = - LabeledRationalFunction( - numerator * other.denominator.toLabeledPolynomial(), - denominator * other.numerator.toLabeledPolynomial() - ) - -// endregion - -// endregion \ No newline at end of file +//// region Operator extensions +// +//// region Field case +// +//fun > LabeledRationalFunction.reduced(): LabeledRationalFunction { +// val greatestCommonDivider = polynomialGCD(numerator, denominator) +// return LabeledRationalFunction( +// numerator / greatestCommonDivider, +// denominator / greatestCommonDivider +// ) +//} +// +//// endregion +// +//// endregion \ No newline at end of file -- 2.34.1 From fb01d851975a1e681f00f6a530431a5dd326421a Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Mon, 14 Mar 2022 22:23:50 +0300 Subject: [PATCH 022/275] Removed extra `JSName` annotations. Now everything builds --- .../kscience/kmath/functions/AbstractPolynomial.kt | 4 ---- .../kmath/functions/AbstractRationalFunction.kt | 10 ---------- 2 files changed, 14 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt index 0ca2d1409..0b16303af 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt @@ -388,25 +388,21 @@ public interface AbstractPolynomialSpaceOverRing, A: * Returns negation of the constant. */ @JvmName("constantUnaryMinus") - @JsName("constantUnaryMinus") public override operator fun C.unaryMinus(): C = ring { -this@unaryMinus } /** * Returns sum of the constants. */ @JvmName("constantPlus") - @JsName("constantPlus") public override operator fun C.plus(other: C): C = ring { this@plus + other } /** * Returns difference of the constants. */ @JvmName("constantMinus") - @JsName("constantMinus") public override operator fun C.minus(other: C): C = ring { this@minus - other } /** * Returns product of the constants. */ @JvmName("constantTimes") - @JsName("constantTimes") public override operator fun C.times(other: C): C = ring { this@times * other } /** diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt index df366f90f..cf8f3a6ef 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt @@ -578,31 +578,26 @@ public interface AbstractRationalFunctionalSpaceOverRing Date: Mon, 14 Mar 2022 23:33:00 +0300 Subject: [PATCH 023/275] Deleted useless annotations `JvmName`, `JsName` and `Suppress` --- .../kmath/functions/AbstractPolynomial.kt | 20 +---------- .../functions/AbstractRationalFunction.kt | 34 ++----------------- .../kmath/functions/LabeledPolynomial.kt | 2 -- .../functions/LabeledRationalFunction.kt | 1 - .../kmath/functions/NumberedPolynomial.kt | 2 -- .../functions/NumberedRationalFunction.kt | 1 - .../kscience/kmath/functions/Polynomial.kt | 3 +- .../kmath/functions/RationalFunction.kt | 1 - .../kmath/functions/numberedPolynomialUtil.kt | 9 ++--- 9 files changed, 9 insertions(+), 64 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt index 0b16303af..b053ffebd 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt @@ -29,21 +29,18 @@ public interface AbstractPolynomialSpace> : Ring

* * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. */ - @JvmName("constantIntPlus") public operator fun C.plus(other: Int): C /** * Returns difference between the constant and the integer represented as constant (member of underlying ring). * * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. */ - @JvmName("constantIntMinus") public operator fun C.minus(other: Int): C /** * Returns product of the constant and the integer represented as constant (member of underlying ring). * * The operation is equivalent to sum of [other] copies of [this]. */ - @JvmName("constantIntTimes") public operator fun C.times(other: Int): C // endregion @@ -53,21 +50,18 @@ public interface AbstractPolynomialSpace> : Ring

* * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. */ - @JvmName("intConstantPlus") public operator fun Int.plus(other: C): C /** * Returns difference between the integer represented as constant (member of underlying ring) and the constant. * * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. */ - @JvmName("intConstantMinus") public operator fun Int.minus(other: C): C /** * Returns product of the integer represented as constant (member of underlying ring) and the constant. * * The operation is equivalent to sum of [this] copies of [other]. */ - @JvmName("intConstantTimes") public operator fun Int.times(other: C): C // endregion @@ -148,32 +142,26 @@ public interface AbstractPolynomialSpace> : Ring

/** * Check if the instant is zero constant. */ - @JvmName("constantIsZero") public fun C.isZero(): Boolean = this == constantZero /** * Check if the instant is NOT zero constant. */ - @JvmName("constantIsNotZero") public fun C.isNotZero(): Boolean = !isZero() /** * Check if the instant is unit constant. */ - @JvmName("constantIsOne") public fun C.isOne(): Boolean = this == constantOne /** * Check if the instant is NOT unit constant. */ - @JvmName("constantIsNotOne") public fun C.isNotOne(): Boolean = !isOne() /** * Check if the instant is minus unit constant. */ - @JvmName("constantIsMinusOne") public fun C.isMinusOne(): Boolean = this == -constantOne /** * Check if the instant is NOT minus unit constant. */ - @JvmName("constantIsNotMinusOne") public fun C.isNotMinusOne(): Boolean = !isMinusOne() /** @@ -330,7 +318,7 @@ public interface AbstractPolynomialSpace> : Ring

* @param C the type of constants. Polynomials have them as a coefficients in their terms. * @param P the type of polynomials. */ -@Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") +@Suppress("INAPPLICABLE_JVM_NAME") public interface AbstractPolynomialSpaceOverRing, A: Ring> : AbstractPolynomialSpace { public val ring: A @@ -341,21 +329,18 @@ public interface AbstractPolynomialSpaceOverRing, A: * * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. */ - @JvmName("constantIntPlus") public override operator fun C.plus(other: Int): C = ring { optimizedAddMultiplied(this@plus, one, other) } /** * Returns difference between the constant and the integer represented as constant (member of underlying ring). * * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. */ - @JvmName("constantIntMinus") public override operator fun C.minus(other: Int): C = ring { optimizedAddMultiplied(this@minus, one, -other) } /** * Returns product of the constant and the integer represented as constant (member of underlying ring). * * The operation is equivalent to sum of [other] copies of [this]. */ - @JvmName("constantIntTimes") public override operator fun C.times(other: Int): C = ring { optimizedMultiply(this@times, other) } // endregion @@ -365,21 +350,18 @@ public interface AbstractPolynomialSpaceOverRing, A: * * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. */ - @JvmName("intConstantPlus") public override operator fun Int.plus(other: C): C = ring { optimizedAddMultiplied(other, one, this@plus) } /** * Returns difference between the integer represented as constant (member of underlying ring) and the constant. * * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. */ - @JvmName("intConstantMinus") public override operator fun Int.minus(other: C): C = ring { optimizedAddMultiplied(-other, one, this@minus) } /** * Returns product of the integer represented as constant (member of underlying ring) and the constant. * * The operation is equivalent to sum of [this] copies of [other]. */ - @JvmName("intConstantTimes") public override operator fun Int.times(other: C): C = ring { optimizedMultiply(other, this@times) } // endregion diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt index cf8f3a6ef..f8d3bb99b 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt @@ -28,21 +28,18 @@ public interface AbstractRationalFunctionalSpace, R: * * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. */ - @JvmName("constantIntPlus") public operator fun C.plus(other: Int): C /** * Returns difference between the constant and the integer represented as constant (member of underlying ring). * * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. */ - @JvmName("constantIntMinus") public operator fun C.minus(other: Int): C /** * Returns product of the constant and the integer represented as constant (member of underlying ring). * * The operation is equivalent to sum of [other] copies of [this]. */ - @JvmName("constantIntTimes") public operator fun C.times(other: Int): C // endregion @@ -52,21 +49,18 @@ public interface AbstractRationalFunctionalSpace, R: * * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. */ - @JvmName("intConstantPlus") public operator fun Int.plus(other: C): C /** * Returns difference between the integer represented as constant (member of underlying ring) and the constant. * * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. */ - @JvmName("intConstantMinus") public operator fun Int.minus(other: C): C /** * Returns product of the integer represented as constant (member of underlying ring) and the constant. * * The operation is equivalent to sum of [this] copies of [other]. */ - @JvmName("intConstantTimes") public operator fun Int.times(other: C): C // endregion @@ -189,32 +183,26 @@ public interface AbstractRationalFunctionalSpace, R: /** * Check if the instant is zero constant. */ - @JvmName("constantIsZero") public fun C.isZero(): Boolean = this == constantZero /** * Check if the instant is NOT zero constant. */ - @JvmName("constantIsNotZero") public fun C.isNotZero(): Boolean = !isZero() /** * Check if the instant is unit constant. */ - @JvmName("constantIsOne") public fun C.isOne(): Boolean = this == constantOne /** * Check if the instant is NOT unit constant. */ - @JvmName("constantIsNotOne") public fun C.isNotOne(): Boolean = !isOne() /** * Check if the instant is minus unit constant. */ - @JvmName("constantIsMinusOne") public fun C.isMinusOne(): Boolean = this == -constantOne /** * Check if the instant is NOT minus unit constant. */ - @JvmName("constantIsNotMinusOne") public fun C.isNotMinusOne(): Boolean = !isMinusOne() /** @@ -520,7 +508,7 @@ public interface AbstractRationalFunctionalSpace, R: // endregion } -@Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") +@Suppress("INAPPLICABLE_JVM_NAME") public interface AbstractRationalFunctionalSpaceOverRing, R: AbstractRationalFunction, A: Ring> : AbstractRationalFunctionalSpace { public val ring: A @@ -531,21 +519,18 @@ public interface AbstractRationalFunctionalSpaceOverRing, R: AbstractRationalFunction, A: Ring> : AbstractRationalFunctionalSpace { public val polynomialRing: AbstractPolynomialSpace @@ -622,21 +604,18 @@ public interface AbstractRationalFunctionalSpaceOverPolynomialSpace.cleanUp() = filterValues { it > 0U } * @param A the intersection of [Ring] of [C] and [ScaleOperations] of [C]. * @param ring the [A] instance. */ -@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE", "INAPPLICABLE_JVM_NAME") public class LabeledPolynomialSpace>( public override val ring: A, ) : AbstractPolynomialSpaceOverRing, A> { @@ -768,7 +767,6 @@ public class LabeledPolynomialSpace>( override val one: LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to constantOne)) // TODO: Docs - @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") override infix fun LabeledPolynomial.equalsTo(other: LabeledPolynomial): Boolean = when { this === other -> true diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt index 203c9e07c..2bec1f3a4 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt @@ -305,7 +305,6 @@ public class LabeledRationalFunctionSpace>( /** * Checks equality of the rational functions. */ - @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") public override infix fun LabeledRationalFunction.equalsTo(other: LabeledRationalFunction): Boolean { if (this === other) return true diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index 39ca43945..de5cc5658 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -263,7 +263,6 @@ public fun > C.asNumberedPolynomial() : NumberedPolynomial = Nu * @param A the intersection of [Ring] of [C] and [ScaleOperations] of [C]. * @param ring the [A] instance. */ -@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE", "INAPPLICABLE_JVM_NAME") public open class NumberedPolynomialSpace>( public final override val ring: A, ) : AbstractPolynomialSpaceOverRing, A> { @@ -532,7 +531,6 @@ public open class NumberedPolynomialSpace>( ) // TODO: Docs - @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") override infix fun NumberedPolynomial.equalsTo(other: NumberedPolynomial): Boolean = when { this === other -> true diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt index aff18d1f4..2053cc7f9 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt @@ -302,7 +302,6 @@ public class NumberedRationalFunctionSpace> ( /** * Checks equality of the rational functions. */ - @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") public override infix fun NumberedRationalFunction.equalsTo(other: NumberedRationalFunction): Boolean { if (this === other) return true diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 49184468b..802ff7ea2 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -66,7 +66,7 @@ public fun T.asPolynomial() : Polynomial = Polynomial(listOf(this)) * @param A type of underlying ring of constants. It's [Ring] of [C]. * @param ring underlying ring of constants of type [A]. */ -@Suppress("INAPPLICABLE_JVM_NAME") // TODO: KT-31420 +//@Suppress("INAPPLICABLE_JVM_NAME") // TODO: KT-31420 public open class PolynomialSpace>( public final override val ring: A, ) : AbstractPolynomialSpaceOverRing, A> { @@ -322,7 +322,6 @@ public open class PolynomialSpace>( override val zero: Polynomial = Polynomial(emptyList()) override val one: Polynomial = Polynomial(listOf(constantZero)) - @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") public override infix fun Polynomial.equalsTo(other: Polynomial): Boolean = when { this === other -> true diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index e9916b634..0842f0938 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -287,7 +287,6 @@ public class RationalFunctionSpace> ( /** * Checks equality of the rational functions. */ - @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals") public override infix fun RationalFunction.equalsTo(other: RationalFunction): Boolean = when { this === other -> true diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt index d4053442d..558afa744 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt @@ -6,6 +6,7 @@ import kotlin.contracts.* import kotlin.jvm.JvmName + // TODO: Docs // region Sort of legacy @@ -485,8 +486,8 @@ public fun NumberedPolynomial.substitute(args: Map): Number val deg = degs.getOrElse(variable) { 0u } if (deg == 0u) product else product * substitutor.pow(deg.toInt()) } - if (newDegs !in acc) acc[newDegs] = c - else acc[newDegs] = acc[newDegs]!! + c + if (newDegs !in acc) acc[newDegs] = newC + else acc[newDegs] = acc[newDegs]!! + newC } return NumberedPolynomial(acc) } @@ -504,8 +505,8 @@ public fun NumberedPolynomial.substitute(ring: Ring, args: Map val deg = degs.getOrElse(variable) { 0u } if (deg == 0u) product else product * power(substitutor, deg) } - if (newDegs !in acc) acc[newDegs] = c - else acc[newDegs] = acc[newDegs]!! + c + if (newDegs !in acc) acc[newDegs] = newC + else acc[newDegs] = acc[newDegs]!! + newC } return NumberedPolynomial(acc) } -- 2.34.1 From ebd7f799adae2047eb5acdfec6ef5345e2a7c3d6 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 15 Mar 2022 00:47:23 +0300 Subject: [PATCH 024/275] Attempts to implement derivatives and antiderivatives --- .../kmath/functions/numberedPolynomialUtil.kt | 175 ++++++++++++++---- .../kmath/functions/polynomialUtil.kt | 32 +++- 2 files changed, 171 insertions(+), 36 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt index 558afa744..b7620e792 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt @@ -545,62 +545,169 @@ public fun > NumberedPolynomial.asPolynomialFunctionOver(ring: * Returns algebraic derivative of received polynomial. */ @UnstableKMathAPI -public fun NumberedPolynomial.derivativeBy( +public fun > NumberedPolynomial.derivativeWithRespectTo( algebra: A, variable: Int, -): Polynomial where A : Ring, A : NumericAlgebra = algebra { - TODO() +): NumberedPolynomial = algebra { + NumberedPolynomial( + buildMap(coefficients.size) { + coefficients.forEach { (degs, c) -> + put( + degs.mapIndexed { index, deg -> + when { + index != variable -> deg + deg > 0u -> deg - 1u + else -> return@forEach + } + }, + optimizedMultiply(c, degs.getOrElse(variable) { 1u }.toInt()) + ) + } + } + ) +} + +/** + * Returns algebraic derivative of received polynomial. + */ // TODO: This one does not work!!! +@UnstableKMathAPI +public fun > NumberedPolynomial.derivativeWithRespectTo( + algebra: A, + variables: IntArray, +): NumberedPolynomial = algebra { + NumberedPolynomial( + buildMap(coefficients.size) { + coefficients.forEach { (degs, c) -> + put( + degs.mapIndexed { index, deg -> + when { + index !in variables -> deg + deg > 0u -> deg - 1u + else -> return@forEach + } + }, + optimizedMultiply(c, variables.fold(1u) { acc, variable -> acc * degs.getOrElse(variable) { 1u } }.toInt()) + ) + } + } + ) +} + +/** + * Returns algebraic derivative of received polynomial. + */ // TODO: This one does not work!!! +@UnstableKMathAPI +public fun > NumberedPolynomial.derivativeWithRespectTo( + algebra: A, + variables: Collection, +): NumberedPolynomial = algebra { + NumberedPolynomial( + buildMap(coefficients.size) { + coefficients.forEach { (degs, c) -> + put( + degs.mapIndexed { index, deg -> + when { + index !in variables -> deg + deg > 0u -> deg - 1u + else -> return@forEach + } + }, + optimizedMultiply(c, variables.fold(1u) { acc, variable -> acc * degs.getOrElse(variable) { 1u } }.toInt()) + ) + } + } + ) } /** * Returns algebraic derivative of received polynomial. */ @UnstableKMathAPI -public fun NumberedPolynomial.derivativeBy( - algebra: A, - variables: IntArray, -): Polynomial where A : Ring, A : NumericAlgebra = algebra { - TODO() -} - -/** - * Returns algebraic derivative of received polynomial. - */ -@UnstableKMathAPI -public fun NumberedPolynomial.derivativeBy( - algebra: A, - variables: Collection, -): Polynomial where A : Ring, A : NumericAlgebra = derivativeBy(algebra, variables.toIntArray()) - -/** - * Create a polynomial witch represents indefinite integral version of this polynomial - */ -@UnstableKMathAPI -public fun NumberedPolynomial.antiderivativeBy( +public fun > NumberedPolynomial.nthDerivativeWithRespectTo( algebra: A, variable: Int, -): Polynomial where A : Field, A : NumericAlgebra = algebra { - TODO() + order: UInt +): NumberedPolynomial = algebra { + NumberedPolynomial( + buildMap(coefficients.size) { + coefficients.forEach { (degs, c) -> + put( + degs.mapIndexed { index, deg -> + when { + index != variable -> deg + deg >= order -> deg - order + else -> return@forEach + } + }, + degs.getOrElse(variable) { 1u }.toInt().let { + (0u until order).fold(c) { acc, ord -> + optimizedMultiply(acc, ord.toInt()) + } + } + ) + } + } + ) } /** - * Create a polynomial witch represents indefinite integral version of this polynomial + * Returns algebraic antiderivative of received polynomial. */ @UnstableKMathAPI -public fun NumberedPolynomial.antiderivativeBy( +public fun > NumberedPolynomial.antiderivativeWithRespectTo( + algebra: A, + variable: Int, +): NumberedPolynomial = algebra { + NumberedPolynomial( + buildMap(coefficients.size) { + coefficients.forEach { (degs, c) -> + put( + degs.mapIndexed { index, deg -> if(index != variable) deg else deg + 1u }, + c / optimizedMultiply(one, degs.getOrElse(variable) { 1u }.toInt()) + ) + } + } + ) +} + +/** + * Returns algebraic antiderivative of received polynomial. + */ // TODO: This one does not work!!! +@UnstableKMathAPI +public fun > NumberedPolynomial.antiderivativeWithRespectTo( algebra: A, variables: IntArray, -): Polynomial where A : Field, A : NumericAlgebra = algebra { - TODO() +): NumberedPolynomial = algebra { + NumberedPolynomial( + buildMap(coefficients.size) { + coefficients.forEach { (degs, c) -> + put( + degs.mapIndexed { index, deg -> if(index !in variables) deg else deg + 1u }, + c / optimizedMultiply(one, variables.fold(1u) { acc, variable -> acc * degs.getOrElse(variable) { 1u } }.toInt()) + ) + } + } + ) } /** - * Create a polynomial witch represents indefinite integral version of this polynomial - */ + * Returns algebraic antiderivative of received polynomial. + */ // TODO: This one does not work!!! @UnstableKMathAPI -public fun NumberedPolynomial.antiderivativeBy( +public fun > NumberedPolynomial.antiderivativeWithRespectTo( algebra: A, variables: Collection, -): Polynomial where A : Field, A : NumericAlgebra = antiderivativeBy(algebra, variables.toIntArray()) +): NumberedPolynomial = algebra { + NumberedPolynomial( + buildMap(coefficients.size) { + coefficients.forEach { (degs, c) -> + put( + degs.mapIndexed { index, deg -> if(index !in variables) deg else deg + 1u }, + c / optimizedMultiply(one, variables.fold(1u) { acc, variable -> acc * degs.getOrElse(variable) { 1u } }.toInt()) + ) + } + } + ) +} // endregion \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt index 4d99b3a45..7e40b6246 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt @@ -109,11 +109,23 @@ public fun > Polynomial.asPolynomialFunctionOver(ring: A): (Po public fun Polynomial.derivative( algebra: A, ): Polynomial where A : Ring, A : NumericAlgebra = algebra { - Polynomial(coefficients.drop(1).mapIndexed { index, t -> number(index) * t }) + Polynomial(coefficients.drop(1).mapIndexed { index, c -> number(index) * c }) } /** - * Create a polynomial witch represents indefinite integral version of this polynomial + * Returns algebraic derivative of received polynomial. + */ +@UnstableKMathAPI +public fun Polynomial.nthDerivative( + algebra: A, + order: UInt, +): Polynomial where A : Ring, A : NumericAlgebra = algebra { + TODO() + Polynomial(coefficients.drop(order.toInt()).mapIndexed { index, c -> number(index) * c }) +} + +/** + * Returns algebraic antiderivative of received polynomial. */ @UnstableKMathAPI public fun Polynomial.antiderivative( @@ -126,6 +138,22 @@ public fun Polynomial.antiderivative( Polynomial(integratedCoefficients) } +/** + * Returns algebraic antiderivative of received polynomial. + */ +@UnstableKMathAPI +public fun Polynomial.nthAntiderivative( + algebra: A, + order: UInt, +): Polynomial where A : Field, A : NumericAlgebra = algebra { + TODO() + val integratedCoefficients = buildList(coefficients.size + 1) { + add(zero) + coefficients.forEachIndexed{ index, t -> add(t / number(index + 1)) } + } + Polynomial(integratedCoefficients) +} + /** * Compute a definite integral of a given polynomial in a [range] */ -- 2.34.1 From f86529d65944016631efe09218c4828feed32f03 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 15 Mar 2022 15:35:17 +0300 Subject: [PATCH 025/275] Optimized `optimizedMultiply` and `optimizedAddMultiplied` for cases of negative value of `other` and `multiplier` --- .../kscience/kmath/functions/algebraicStub.kt | 59 +++++++++++++------ 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt index 9e5043b8c..3c37a01ec 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt @@ -16,17 +16,11 @@ import space.kscience.kmath.operations.Group * @receiver the multiplicand. * @param other the multiplier. * @return the difference. + * @author Gleb Minaev */ -internal tailrec fun Group.optimizedMultiply(arg: C, other: Int): C = - when { - other == 0 -> zero - other == 1 -> arg - other == -1 -> -arg - other % 2 == 0 -> optimizedMultiply(arg + arg, other / 2) - other % 2 == 1 -> optimizedAddMultiplied(arg, arg + arg, other / 2) - other % 2 == -1 -> optimizedAddMultiplied(-arg, arg + arg, other / 2) - else -> error("Error in multiplication group instant by integer: got reminder by division by 2 different from 0, 1 and -1") - } +internal fun Group.optimizedMultiply(arg: C, other: Int): C = + if (other >= 0) optimizedMultiply(arg, other.toUInt()) + else optimizedMultiply(arg, (-other).toUInt()) // TODO: Move receiver to context receiver /** @@ -40,12 +34,43 @@ internal tailrec fun Group.optimizedMultiply(arg: C, other: Int): C = * @author Gleb Minaev */ internal tailrec fun Group.optimizedAddMultiplied(base: C, arg: C, multiplier: Int): C = + if (multiplier >= 0) optimizedAddMultiplied(base, arg, multiplier.toUInt()) + else optimizedAddMultiplied(base, arg, (-multiplier).toUInt()) + +// TODO: Move receiver to context receiver +/** + * Multiplication of element and integer. + * + * @receiver the multiplicand. + * @param other the multiplier. + * @return the difference. + * @author Gleb Minaev + */ +internal tailrec fun Group.optimizedMultiply(arg: C, other: UInt): C = when { - multiplier == 0 -> base - multiplier == 1 -> base + arg - multiplier == -1 -> base - arg - multiplier % 2 == 0 -> optimizedAddMultiplied(base, arg + arg, multiplier / 2) - multiplier % 2 == 1 -> optimizedAddMultiplied(base + arg, arg + arg, multiplier / 2) - multiplier % 2 == -1 -> optimizedAddMultiplied(base + arg, arg + arg, multiplier / 2) - else -> error("Error in multiplication group instant by integer: got reminder by division by 2 different from 0, 1 and -1") + other == 0u -> zero + other == 1u -> arg + other % 2u == 0u -> optimizedMultiply(arg + arg, other / 2u) + other % 2u == 1u -> optimizedAddMultiplied(arg, arg + arg, other / 2u) + else -> error("Error in multiplication group instant by unsigned integer: got reminder by division by 2 different from 0 and 1") + } + +// TODO: Move receiver to context receiver +/** + * Adds product of [arg] and [multiplier] to [base]. + * + * @receiver the algebra to provide multiplication. + * @param base the augend. + * @param arg the multiplicand. + * @param multiplier the multiplier. + * @return sum of the augend [base] and product of the multiplicand [arg] and the multiplier [multiplier]. + * @author Gleb Minaev + */ +internal tailrec fun Group.optimizedAddMultiplied(base: C, arg: C, multiplier: UInt): C = + when { + multiplier == 0u -> base + multiplier == 1u -> base + arg + multiplier % 2u == 0u -> optimizedAddMultiplied(base, arg + arg, multiplier / 2u) + multiplier % 2u == 1u -> optimizedAddMultiplied(base + arg, arg + arg, multiplier / 2u) + 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 -- 2.34.1 From 79736a0a9b6450df9ae0a7d7209b8aa7603d36c4 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 15 Mar 2022 15:36:10 +0300 Subject: [PATCH 026/275] Forgot to remove unnecessary `tailrec` --- .../kotlin/space/kscience/kmath/functions/algebraicStub.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt index 3c37a01ec..537184ba3 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt @@ -33,7 +33,7 @@ internal fun Group.optimizedMultiply(arg: C, other: Int): C = * @return sum of the augend [base] and product of the multiplicand [arg] and the multiplier [multiplier]. * @author Gleb Minaev */ -internal tailrec fun Group.optimizedAddMultiplied(base: C, arg: C, multiplier: Int): C = +internal fun Group.optimizedAddMultiplied(base: C, arg: C, multiplier: Int): C = if (multiplier >= 0) optimizedAddMultiplied(base, arg, multiplier.toUInt()) else optimizedAddMultiplied(base, arg, (-multiplier).toUInt()) -- 2.34.1 From 1754ae06951ff0964239cc7c822b869b31ab371e Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 15 Mar 2022 16:43:22 +0300 Subject: [PATCH 027/275] Added some docs --- .../kmath/functions/AbstractPolynomial.kt | 8 +- .../functions/AbstractRationalFunction.kt | 36 +++++- .../kmath/functions/LabeledPolynomial.kt | 60 +++++++++- .../functions/LabeledRationalFunction.kt | 7 +- .../kmath/functions/NumberedPolynomial.kt | 69 ++++++++++- .../functions/NumberedRationalFunction.kt | 7 +- .../kscience/kmath/functions/Polynomial.kt | 112 +++++++++++++++--- .../kmath/functions/RationalFunction.kt | 7 +- 8 files changed, 271 insertions(+), 35 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt index b053ffebd..8bd8697e3 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt @@ -18,7 +18,7 @@ public interface AbstractPolynomial /** * 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 a coefficients in their terms. + * @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") @@ -313,10 +313,12 @@ public interface AbstractPolynomialSpace> : Ring

} /** - * Abstraction of ring of polynomials of type [P] over ring of constants of type [C]. + * 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 a coefficients in their terms. + * @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") public interface AbstractPolynomialSpaceOverRing, A: Ring> : AbstractPolynomialSpace { diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt index f8d3bb99b..685cf4ca3 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt @@ -20,6 +20,14 @@ public interface AbstractRationalFunction> { 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 in them. + * @param R the type of rational functions. + */ // TODO: Add support of field @Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") public interface AbstractRationalFunctionalSpace, R: AbstractRationalFunction> : Ring { // region Constant-integer relation @@ -508,6 +516,15 @@ public interface AbstractRationalFunctionalSpace, R: // endregion } +/** + * 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. + */ // TODO: Add support of field @Suppress("INAPPLICABLE_JVM_NAME") public interface AbstractRationalFunctionalSpaceOverRing, R: AbstractRationalFunction, A: Ring> : AbstractRationalFunctionalSpace { @@ -593,10 +610,25 @@ public interface AbstractRationalFunctionalSpaceOverRing, R: AbstractRationalFunction, A: Ring> : AbstractRationalFunctionalSpace { +public interface AbstractRationalFunctionalSpaceOverPolynomialSpace< + C, + P: AbstractPolynomial, + R: AbstractRationalFunction, + AP: AbstractPolynomialSpace, + > : AbstractRationalFunctionalSpace { - public val polynomialRing: AbstractPolynomialSpace + public val polynomialRing: AP // region Constant-integer relation /** diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt index 81aabb4a4..ebdaa6e26 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -384,6 +384,11 @@ public class LabeledPolynomialSpace>( // endregion // region Polynomial-integer relation + /** + * Returns sum of the polynomial and the integer represented as polynomial. + * + * The operation is equivalent to adding [other] copies of unit polynomial to [this]. + */ public override operator fun LabeledPolynomial.plus(other: Int): LabeledPolynomial = if (other == 0) this else @@ -399,6 +404,11 @@ public class LabeledPolynomialSpace>( else this[degs] = result } ) + /** + * Returns difference between the polynomial and the integer represented as polynomial. + * + * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. + */ public override operator fun LabeledPolynomial.minus(other: Int): LabeledPolynomial = if (other == 0) this else @@ -414,6 +424,11 @@ public class LabeledPolynomialSpace>( else this[degs] = result } ) + /** + * Returns product of the polynomial and the integer represented as polynomial. + * + * The operation is equivalent to sum of [other] copies of [this]. + */ public override operator fun LabeledPolynomial.times(other: Int): LabeledPolynomial = if (other == 0) zero else LabeledPolynomial( @@ -425,6 +440,11 @@ public class LabeledPolynomialSpace>( // endregion // region Integer-polynomial relation + /** + * Returns sum of the integer represented as 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 = if (this == 0) other else @@ -440,6 +460,11 @@ public class LabeledPolynomialSpace>( else this[degs] = result } ) + /** + * Returns difference between the integer represented as 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 = if (this == 0) other else @@ -455,6 +480,11 @@ public class LabeledPolynomialSpace>( else this[degs] = result } ) + /** + * Returns product of the integer represented as polynomial and the polynomial. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ public override operator fun Int.times(other: LabeledPolynomial): LabeledPolynomial = if (this == 0) zero else LabeledPolynomial( @@ -514,6 +544,9 @@ public class LabeledPolynomialSpace>( // endregion // region Constant-polynomial relation + /** + * Returns sum of the constant represented as polynomial and the polynomial. + */ override operator fun C.plus(other: LabeledPolynomial): LabeledPolynomial = if (this.isZero()) other else with(other.coefficients) { @@ -530,6 +563,9 @@ public class LabeledPolynomialSpace>( } ) } + /** + * Returns difference between the constant represented as polynomial and the polynomial. + */ override operator fun C.minus(other: LabeledPolynomial): LabeledPolynomial = if (this.isZero()) other else with(other.coefficients) { @@ -548,6 +584,9 @@ public class LabeledPolynomialSpace>( } ) } + /** + * Returns product of the constant represented as polynomial and the polynomial. + */ override operator fun C.times(other: LabeledPolynomial): LabeledPolynomial = if (this.isZero()) zero else LabeledPolynomial( @@ -560,7 +599,7 @@ public class LabeledPolynomialSpace>( // region Polynomial-constant relation /** - * Returns sum of the polynomials. [other] is interpreted as [UnivariatePolynomial]. + * Returns sum of the constant represented as polynomial and the polynomial. */ override operator fun LabeledPolynomial.plus(other: C): LabeledPolynomial = if (other.isZero()) this @@ -579,7 +618,7 @@ public class LabeledPolynomialSpace>( ) } /** - * Returns difference of the polynomials. [other] is interpreted as [UnivariatePolynomial]. + * Returns difference between the constant represented as polynomial and the polynomial. */ override operator fun LabeledPolynomial.minus(other: C): LabeledPolynomial = if (other.isZero()) this @@ -600,7 +639,7 @@ public class LabeledPolynomialSpace>( ) } /** - * Returns product of the polynomials. [other] is interpreted as [UnivariatePolynomial]. + * Returns product of the constant represented as polynomial and the polynomial. */ override operator fun LabeledPolynomial.times(other: C): LabeledPolynomial = if (other.isZero()) zero @@ -763,10 +802,18 @@ public class LabeledPolynomialSpace>( ) } + /** + * Instance of zero polynomial (zero of the polynomial ring). + */ override val zero: LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to constantZero)) + /** + * Instance of unit polynomial (unit of the polynomial ring). + */ override val one: LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to constantOne)) - // TODO: Docs + /** + * Checks equality of the polynomials. + */ override infix fun LabeledPolynomial.equalsTo(other: LabeledPolynomial): Boolean = when { this === other -> true @@ -832,7 +879,10 @@ public class LabeledPolynomialSpace>( } foundAbsoluteTermAndItIsNotZero } - + /** + * If polynomial is a constant polynomial represents and returns it as constant. + * Otherwise, (when the polynomial is not constant polynomial) returns `null`. + */ override fun LabeledPolynomial.asConstantOrNull(): C? = with(coefficients) { if(isConstant()) getOrElse(emptyMap()) { constantZero } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt index 2bec1f3a4..df4441127 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt @@ -85,7 +85,12 @@ internal fun labeledRationalFunctionError(message: Any): Nothing = throw Labeled public class LabeledRationalFunctionSpace>( public val ring: A, -) : AbstractRationalFunctionalSpaceOverPolynomialSpace, LabeledRationalFunction, A> { +) : AbstractRationalFunctionalSpaceOverPolynomialSpace< + C, + LabeledPolynomial, + LabeledRationalFunction, + LabeledPolynomialSpace, + > { override val polynomialRing : LabeledPolynomialSpace = LabeledPolynomialSpace(ring) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index de5cc5658..86c76949b 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -267,6 +267,11 @@ public open class NumberedPolynomialSpace>( public final override val ring: A, ) : AbstractPolynomialSpaceOverRing, A> { // region Polynomial-integer relation + /** + * Returns sum of the polynomial and the integer represented as 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 @@ -282,6 +287,11 @@ public open class NumberedPolynomialSpace>( else this[degs] = result } ) + /** + * Returns difference between the polynomial and the integer represented as 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 @@ -297,6 +307,11 @@ public open class NumberedPolynomialSpace>( else this[degs] = result } ) + /** + * Returns product of the polynomial and the integer represented as polynomial. + * + * The operation is equivalent to sum of [other] copies of [this]. + */ public override operator fun NumberedPolynomial.times(other: Int): NumberedPolynomial = if (other == 0) zero else NumberedPolynomial( @@ -308,6 +323,11 @@ public open class NumberedPolynomialSpace>( // endregion // region Integer-polynomial relation + /** + * Returns sum of the integer represented as 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 @@ -323,6 +343,11 @@ public open class NumberedPolynomialSpace>( else this[degs] = result } ) + /** + * Returns difference between the integer represented as 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 = if (this == 0) other else @@ -338,6 +363,11 @@ public open class NumberedPolynomialSpace>( else this[degs] = result } ) + /** + * Returns product of the integer represented as polynomial and the polynomial. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ public override operator fun Int.times(other: NumberedPolynomial): NumberedPolynomial = if (this == 0) zero else NumberedPolynomial( @@ -349,6 +379,9 @@ public open class NumberedPolynomialSpace>( // endregion // region Constant-polynomial relation + /** + * Returns sum of the constant represented as polynomial and the polynomial. + */ override operator fun C.plus(other: NumberedPolynomial): NumberedPolynomial = if (this.isZero()) other else with(other.coefficients) { @@ -365,6 +398,9 @@ public open class NumberedPolynomialSpace>( } ) } + /** + * Returns difference between the constant represented as polynomial and the polynomial. + */ override operator fun C.minus(other: NumberedPolynomial): NumberedPolynomial = if (this.isZero()) -other else with(other.coefficients) { @@ -383,6 +419,9 @@ public open class NumberedPolynomialSpace>( } ) } + /** + * Returns product of the constant represented as polynomial and the polynomial. + */ override operator fun C.times(other: NumberedPolynomial): NumberedPolynomial = if (this.isZero()) zero else NumberedPolynomial( @@ -395,7 +434,7 @@ public open class NumberedPolynomialSpace>( // region Polynomial-constant relation /** - * Returns sum of the polynomials. [other] is interpreted as [NumberedPolynomial]. + * Returns sum of the constant represented as polynomial and the polynomial. */ override operator fun NumberedPolynomial.plus(other: C): NumberedPolynomial = if (other.isZero()) this @@ -414,7 +453,7 @@ public open class NumberedPolynomialSpace>( ) } /** - * Returns difference of the polynomials. [other] is interpreted as [NumberedPolynomial]. + * Returns difference between the constant represented as polynomial and the polynomial. */ override operator fun NumberedPolynomial.minus(other: C): NumberedPolynomial = if (other.isZero()) this @@ -433,7 +472,7 @@ public open class NumberedPolynomialSpace>( ) } /** - * Returns product of the polynomials. [other] is interpreted as [NumberedPolynomial]. + * Returns product of the constant represented as polynomial and the polynomial. */ override operator fun NumberedPolynomial.times(other: C): NumberedPolynomial = if (other.isZero()) zero @@ -496,7 +535,13 @@ public open class NumberedPolynomialSpace>( ) } + /** + * Check if the instant is zero polynomial. + */ public override fun NumberedPolynomial.isZero(): Boolean = coefficients.values.all { it.isZero() } + /** + * Check if the instant is unit polynomial. + */ public override fun NumberedPolynomial.isOne(): Boolean = with(coefficients) { var foundAbsoluteTermAndItIsOne = false @@ -509,6 +554,9 @@ public open class NumberedPolynomialSpace>( } foundAbsoluteTermAndItIsOne } + /** + * Check if the instant is minus unit polynomial. + */ public override fun NumberedPolynomial.isMinusOne(): Boolean = with(coefficients) { var foundAbsoluteTermAndItIsMinusOne = false @@ -522,7 +570,13 @@ public open class NumberedPolynomialSpace>( foundAbsoluteTermAndItIsMinusOne } + /** + * Instance of zero polynomial (zero of the polynomial ring). + */ override val zero: NumberedPolynomial = NumberedPolynomial(emptyMap()) + /** + * Instance of unit polynomial (unit of the polynomial ring). + */ override val one: NumberedPolynomial = NumberedPolynomial( mapOf( @@ -530,7 +584,9 @@ public open class NumberedPolynomialSpace>( ) ) - // TODO: Docs + /** + * Checks equality of the polynomials. + */ override infix fun NumberedPolynomial.equalsTo(other: NumberedPolynomial): Boolean = when { this === other -> true @@ -591,7 +647,10 @@ public open class NumberedPolynomialSpace>( } foundAbsoluteTermAndItIsNotZero } - + /** + * If polynomial is a constant polynomial represents and returns it as constant. + * Otherwise, (when the polynomial is not constant polynomial) returns `null`. + */ override fun NumberedPolynomial.asConstantOrNull(): C? = with(coefficients) { if(isConstant()) getOrElse(emptyList()) { constantZero } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt index 2053cc7f9..a81795c81 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt @@ -82,7 +82,12 @@ internal fun numberedRationalFunctionError(message: Any): Nothing = throw Number public class NumberedRationalFunctionSpace> ( public val ring: A, -) : AbstractRationalFunctionalSpaceOverPolynomialSpace, NumberedRationalFunction, A> { +) : AbstractRationalFunctionalSpaceOverPolynomialSpace< + C, + NumberedPolynomial, + NumberedRationalFunction, + NumberedPolynomialSpace, + > { override val polynomialRing : NumberedPolynomialSpace = NumberedPolynomialSpace(ring) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 802ff7ea2..bdc725e63 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -68,10 +68,15 @@ public fun T.asPolynomial() : Polynomial = Polynomial(listOf(this)) */ //@Suppress("INAPPLICABLE_JVM_NAME") // TODO: KT-31420 public open class PolynomialSpace>( - public final override val ring: A, + public override val ring: A, ) : AbstractPolynomialSpaceOverRing, A> { // region Polynomial-integer relation + /** + * Returns sum of the polynomial and the integer represented as polynomial. + * + * The operation is equivalent to adding [other] copies of unit polynomial to [this]. + */ public override operator fun Polynomial.plus(other: Int): Polynomial = if (other == 0) this else @@ -89,6 +94,11 @@ public open class PolynomialSpace>( } } ) + /** + * Returns difference between the polynomial and the integer represented as polynomial. + * + * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. + */ public override operator fun Polynomial.minus(other: Int): Polynomial = if (other == 0) this else @@ -106,6 +116,11 @@ public open class PolynomialSpace>( } } ) + /** + * Returns product of the polynomial and the integer represented as polynomial. + * + * The operation is equivalent to sum of [other] copies of [this]. + */ public override operator fun Polynomial.times(other: Int): Polynomial = if (other == 0) zero else Polynomial( @@ -116,6 +131,11 @@ public open class PolynomialSpace>( // endregion // region Integer-polynomial relation + /** + * Returns sum of the integer represented as polynomial and the polynomial. + * + * The operation is equivalent to adding [this] copies of unit polynomial to [other]. + */ public override operator fun Int.plus(other: Polynomial): Polynomial = if (this == 0) other else @@ -133,6 +153,11 @@ public open class PolynomialSpace>( } } ) + /** + * Returns difference between the integer represented as polynomial and the polynomial. + * + * The operation is equivalent to subtraction [this] copies of unit polynomial from [other]. + */ public override operator fun Int.minus(other: Polynomial): Polynomial = if (this == 0) other else @@ -152,6 +177,11 @@ public open class PolynomialSpace>( } } ) + /** + * Returns product of the integer represented as polynomial and the polynomial. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ public override operator fun Int.times(other: Polynomial): Polynomial = if (this == 0) zero else Polynomial( @@ -162,6 +192,9 @@ public open class PolynomialSpace>( // endregion // region Constant-polynomial relation + /** + * Returns sum of the constant represented as polynomial and the polynomial. + */ public override operator fun C.plus(other: Polynomial): Polynomial = if (this.isZero()) other else with(other.coefficients) { @@ -180,9 +213,9 @@ public open class PolynomialSpace>( } ) } -// if (degree == -1) UnivariatePolynomial(other) else UnivariatePolynomial( -// listOf(coefficients[0] + other) + coefficients.subList(1, degree + 1) -// ) + /** + * Returns difference between the constant represented as polynomial and the polynomial. + */ public override operator fun C.minus(other: Polynomial): Polynomial = if (this.isZero()) other else with(other.coefficients) { @@ -203,9 +236,9 @@ public open class PolynomialSpace>( } ) } -// if (degree == -1) UnivariatePolynomial(other) else UnivariatePolynomial( -// listOf(coefficients[0] + other) + coefficients.subList(1, degree + 1) -// ) + /** + * Returns product of the constant represented as polynomial and the polynomial. + */ public override operator fun C.times(other: Polynomial): Polynomial = if (this.isZero()) other else Polynomial( @@ -216,6 +249,9 @@ public open class PolynomialSpace>( // endregion // region Polynomial-constant relation + /** + * Returns sum of the constant represented as polynomial and the polynomial. + */ public override operator fun Polynomial.plus(other: C): Polynomial = if (other.isZero()) this else with(coefficients) { @@ -234,9 +270,9 @@ public open class PolynomialSpace>( } ) } -// if (degree == -1) UnivariatePolynomial(other) else UnivariatePolynomial( -// listOf(coefficients[0] + other) + coefficients.subList(1, degree + 1) -// ) + /** + * Returns difference between the constant represented as polynomial and the polynomial. + */ public override operator fun Polynomial.minus(other: C): Polynomial = if (other.isZero()) this else with(coefficients) { @@ -255,9 +291,9 @@ public open class PolynomialSpace>( } ) } -// if (degree == -1) UnivariatePolynomial(-other) else UnivariatePolynomial( -// listOf(coefficients[0] - other) + coefficients.subList(1, degree + 1) -// ) + /** + * Returns product of the constant represented as polynomial and the polynomial. + */ public override operator fun Polynomial.times(other: C): Polynomial = if (other.isZero()) this else Polynomial( @@ -268,8 +304,14 @@ public open class PolynomialSpace>( // endregion // region Polynomial-polynomial relation + /** + * Returns negation of the polynomial. + */ public override operator fun Polynomial.unaryMinus(): Polynomial = Polynomial(coefficients.map { -it }) + /** + * Returns sum of the polynomials. + */ public override operator fun Polynomial.plus(other: Polynomial): Polynomial = Polynomial( (0..max(degree, other.degree)) @@ -282,6 +324,9 @@ public open class PolynomialSpace>( } .ifEmpty { listOf(constantZero) } ) + /** + * Returns difference of the polynomials. + */ public override operator fun Polynomial.minus(other: Polynomial): Polynomial = Polynomial( (0..max(degree, other.degree)) @@ -294,6 +339,9 @@ public open class PolynomialSpace>( } .ifEmpty { listOf(constantZero) } ) + /** + * Returns product of the polynomials. + */ public override operator fun Polynomial.times(other: Polynomial): Polynomial { val thisDegree = degree val otherDegree = other.degree @@ -313,15 +361,39 @@ public open class PolynomialSpace>( } } + /** + * Check if the instant is zero polynomial. + */ public override fun Polynomial.isZero(): Boolean = coefficients.all { it.isZero() } + /** + * Check if the instant is unit polynomial. + */ public override fun Polynomial.isOne(): Boolean = - with(coefficients) { isNotEmpty() && asSequence().withIndex().any { (index, c) -> if (index == 0) c.isOne() else c.isZero() } } // TODO: It's better to write new methods like `anyIndexed`. But what's better way to do it? + with(coefficients) { + isNotEmpty() && + asSequence().withIndex().any { (index, c) -> if (index == 0) c.isOne() else c.isZero() } // TODO: It's better to write new methods like `anyIndexed`. But what's better way to do it? + } + /** + * Check if the instant is minus unit polynomial. + */ public override fun Polynomial.isMinusOne(): Boolean = - with(coefficients) { isNotEmpty() && asSequence().withIndex().any { (index, c) -> if (index == 0) c.isMinusOne() else c.isZero() } } // TODO: It's better to write new methods like `anyIndexed`. But what's better way to do it? + with(coefficients) { + isNotEmpty() && + asSequence().withIndex().any { (index, c) -> if (index == 0) c.isMinusOne() else c.isZero() } // TODO: It's better to write new methods like `anyIndexed`. But what's better way to do it? + } + /** + * Instance of zero polynomial (zero of the polynomial ring). + */ override val zero: Polynomial = Polynomial(emptyList()) + /** + * Instance of unit constant (unit of the underlying ring). + */ override val one: Polynomial = Polynomial(listOf(constantZero)) + /** + * Checks equality of the polynomials. + */ public override infix fun Polynomial.equalsTo(other: Polynomial): Boolean = when { this === other -> true @@ -334,9 +406,16 @@ public open class PolynomialSpace>( // endregion // region Polynomial properties - + /** + * 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 Polynomial.degree: Int get() = coefficients.indexOfLast { it != constantZero } + /** + * If polynomial is a constant polynomial represents and returns it as constant. + * Otherwise, (when the polynomial is not constant polynomial) returns `null`. + */ public override fun Polynomial.asConstantOrNull(): C? = with(coefficients) { when { @@ -345,7 +424,6 @@ public open class PolynomialSpace>( else -> first() } } - public override fun Polynomial.asConstant(): C = asConstantOrNull() ?: error("Can not represent non-constant polynomial as a constant") @Suppress("NOTHING_TO_INLINE") public inline fun Polynomial.substitute(argument: C): C = this.substitute(ring, argument) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index 0842f0938..441136a64 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -67,7 +67,12 @@ internal fun rationalFunctionError(message: Any): Nothing = throw RationalFuncti public class RationalFunctionSpace> ( public val ring: A, -) : AbstractRationalFunctionalSpaceOverPolynomialSpace, RationalFunction, A> { +) : AbstractRationalFunctionalSpaceOverPolynomialSpace< + C, + Polynomial, + RationalFunction, + PolynomialSpace, + > { override val polynomialRing : PolynomialSpace = PolynomialSpace(ring) -- 2.34.1 From 91c9ea61da4f9e3ec60003ce25a6448e9b699b85 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 15 Mar 2022 18:10:11 +0300 Subject: [PATCH 028/275] Added derivative-like functions to `Polynomial` --- .../kscience/kmath/functions/Polynomial.kt | 16 +++---- .../kmath/functions/polynomialUtil.kt | 48 ++++++++++++------- 2 files changed, 39 insertions(+), 25 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index bdc725e63..1ac413818 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -14,7 +14,7 @@ import kotlin.math.min * * @param coefficients constant is the leftmost coefficient. */ -public data class Polynomial(public val coefficients: List) : AbstractPolynomial { +public data class Polynomial(public val coefficients: List) : AbstractPolynomial { override fun toString(): String = "Polynomial$coefficients" } @@ -44,7 +44,7 @@ internal fun polynomialError(message: Any): Nothing = throw PolynomialError(mess * [reverse] parameter is true. */ @Suppress("FunctionName") -public fun Polynomial(coefficients: List, reverse: Boolean = false): Polynomial = +public fun Polynomial(coefficients: List, reverse: Boolean = false): Polynomial = Polynomial(with(coefficients) { if (reverse) reversed() else this }) /** @@ -52,10 +52,10 @@ public fun Polynomial(coefficients: List, reverse: Boolean = false): Poly * [reverse] parameter is true. */ @Suppress("FunctionName") -public fun Polynomial(vararg coefficients: T, reverse: Boolean = false): Polynomial = +public fun Polynomial(vararg coefficients: C, reverse: Boolean = false): Polynomial = Polynomial(with(coefficients) { if (reverse) reversed() else toList() }) -public fun T.asPolynomial() : Polynomial = Polynomial(listOf(this)) +public fun C.asPolynomial() : Polynomial = Polynomial(listOf(this)) // endregion @@ -352,7 +352,7 @@ public open class PolynomialSpace>( Polynomial( (0..(thisDegree + otherDegree)) .map { d -> - (max(0, d - otherDegree)..(min(thisDegree, d))) + (max(0, d - otherDegree)..min(thisDegree, d)) .map { coefficients[it] * other.coefficients[d - it] } .reduce { acc, rational -> acc + rational } } @@ -370,16 +370,14 @@ public open class PolynomialSpace>( */ public override fun Polynomial.isOne(): Boolean = with(coefficients) { - isNotEmpty() && - asSequence().withIndex().any { (index, c) -> if (index == 0) c.isOne() else c.isZero() } // TODO: It's better to write new methods like `anyIndexed`. But what's better way to do it? + isNotEmpty() && withIndex().any { (index, c) -> if (index == 0) c.isOne() else c.isZero() } } /** * Check if the instant is minus unit polynomial. */ public override fun Polynomial.isMinusOne(): Boolean = with(coefficients) { - isNotEmpty() && - asSequence().withIndex().any { (index, c) -> if (index == 0) c.isMinusOne() else c.isZero() } // TODO: It's better to write new methods like `anyIndexed`. But what's better way to do it? + isNotEmpty() && withIndex().any { (index, c) -> if (index == 0) c.isMinusOne() else c.isZero() } } /** diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt index 7e40b6246..a41a6cbd6 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt @@ -9,7 +9,8 @@ import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* import kotlin.contracts.InvocationKind import kotlin.contracts.contract -import kotlin.jvm.JvmName +import kotlin.math.max +import kotlin.math.min import kotlin.math.pow @@ -77,15 +78,32 @@ public fun Polynomial.substitute(ring: Ring, arg: C): C = ring { return result } -// TODO: (Waiting for hero) Replace with optimisation: the [result] may be unboxed, and all operations may be performed -// as soon as possible on it public fun Polynomial.substitute(ring: Ring, arg: Polynomial) : Polynomial = ring.polynomial { if (coefficients.isEmpty()) return zero - var result: Polynomial = coefficients.last().asPolynomial() - for (j in coefficients.size - 2 downTo 0) { - result = (arg * result) + coefficients[j] + + val thisDegree = degree + if (thisDegree == -1) return zero + val argDegree = arg.degree + if (argDegree == -1) return coefficients[0].asPolynomial() + val constantZero = constantZero + val resultCoefs: MutableList = MutableList(thisDegree + argDegree + 1) { constantZero } + val resultCoefsUpdate: MutableList = MutableList(thisDegree + argDegree + 1) { constantZero } + var resultDegree = 0 + for (deg in thisDegree downTo 0) { + resultCoefsUpdate[0] = coefficients[deg] + for (updateDeg in 0 .. resultDegree + argDegree) { + var newC = resultCoefsUpdate[updateDeg] + for (deg1 in max(0, updateDeg - argDegree)..min(resultDegree, updateDeg)) + newC += resultCoefs[deg1] * arg.coefficients[updateDeg - deg1] + resultCoefsUpdate[updateDeg] = newC + } + resultDegree += argDegree + for (updateDeg in 0 .. resultDegree + argDegree) { + resultCoefs[updateDeg] = resultCoefsUpdate[updateDeg] + resultCoefsUpdate[updateDeg] = constantZero + } } - return result + return Polynomial(resultCoefs) } /** @@ -109,7 +127,7 @@ public fun > Polynomial.asPolynomialFunctionOver(ring: A): (Po public fun Polynomial.derivative( algebra: A, ): Polynomial where A : Ring, A : NumericAlgebra = algebra { - Polynomial(coefficients.drop(1).mapIndexed { index, c -> number(index) * c }) + Polynomial(coefficients.drop(1).mapIndexed { index, c -> number(index + 1) * c }) } /** @@ -120,8 +138,7 @@ public fun Polynomial.nthDerivative( algebra: A, order: UInt, ): Polynomial where A : Ring, A : NumericAlgebra = algebra { - TODO() - Polynomial(coefficients.drop(order.toInt()).mapIndexed { index, c -> number(index) * c }) + Polynomial(coefficients.drop(order.toInt()).mapIndexed { index, c -> (1..order.toInt()).fold(c) { acc, i -> acc * number(index + i) } }) } /** @@ -133,7 +150,7 @@ public fun Polynomial.antiderivative( ): Polynomial where A : Field, A : NumericAlgebra = algebra { val integratedCoefficients = buildList(coefficients.size + 1) { add(zero) - coefficients.forEachIndexed{ index, t -> add(t / number(index + 1)) } + coefficients.mapIndexedTo(this) { index, t -> t / number(index + 1) } } Polynomial(integratedCoefficients) } @@ -146,12 +163,11 @@ public fun Polynomial.nthAntiderivative( algebra: A, order: UInt, ): Polynomial where A : Field, A : NumericAlgebra = algebra { - TODO() - val integratedCoefficients = buildList(coefficients.size + 1) { - add(zero) - coefficients.forEachIndexed{ index, t -> add(t / number(index + 1)) } + val newCoefficients = buildList(coefficients.size + order.toInt()) { + repeat(order.toInt()) { add(zero) } + coefficients.mapIndexedTo(this) { index, c -> (1..order.toInt()).fold(c) { acc, i -> acc / number(index + i) } } } - Polynomial(integratedCoefficients) + return Polynomial(newCoefficients) } /** -- 2.34.1 From 1f9d8d34f5f0476b4ea553bdd2c99a7406d30f61 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 15 Mar 2022 20:18:39 +0300 Subject: [PATCH 029/275] Tried to add constructors and/or fabrics for polynomials --- .../kmath/functions/LabeledPolynomial.kt | 247 ++---------------- .../kmath/functions/NumberedPolynomial.kt | 223 +++++----------- .../kscience/kmath/functions/Polynomial.kt | 27 +- 3 files changed, 122 insertions(+), 375 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt index ebdaa6e26..56dad975d 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -73,254 +73,59 @@ internal fun Map.cleanUp() = filterValues { it > 0U } // region Constructors and converters -///** -// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received -// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. -// * -// * @param pairs Collection of pairs that represent monomials. -// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. -// * -// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. -// */ -//context(A) -//internal fun > LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true): LabeledPolynomial { -// if (!toCheckInput) return LabeledPolynomial(coefs) +//context(LabeledPolynomialSpace>) +//@Suppress("FunctionName") +//internal fun LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = false) : LabeledPolynomial { +// if (!toCheckInput) return LabeledPolynomial(coefs) // -// // Map for cleaned coefficients. // val fixedCoefs = mutableMapOf, C>() // -// // Cleaning the degrees, summing monomials of the same degrees. // for (entry in coefs) { // val key = entry.key.cleanUp() // val value = entry.value // fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value // } // -// // Removing zero monomials. -// return LabeledPolynomial( -// fixedCoefs -// .filter { it.value.isNotZero() } +// return LabeledPolynomial( +// fixedCoefs.filterValues { it.isNotZero() } // ) //} -///** -// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received -// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. -// * -// * @param pairs Collection of pairs that represent monomials. -// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. -// * -// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. -// */ -//context(A) -//internal fun > LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean): LabeledPolynomial { -// if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) // -// // Map for cleaned coefficients. +//context(LabeledPolynomialSpace>) +//@Suppress("FunctionName") +//internal fun LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = false) : LabeledPolynomial { +// if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) +// // val fixedCoefs = mutableMapOf, C>() // -// // Cleaning the degrees, summing monomials of the same degrees. // for (entry in pairs) { // val key = entry.first.cleanUp() // val value = entry.second // fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value // } // -// // Removing zero monomials. -// return LabeledPolynomial( +// return LabeledPolynomial( // fixedCoefs.filterValues { it.isNotZero() } // ) //} -///** -// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received -// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. -// * -// * @param pairs Collection of pairs that represents monomials. -// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. -// * -// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. -// */ -//context(A) -//internal fun > LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean): LabeledPolynomial { -// if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) // -// // Map for cleaned coefficients. -// val fixedCoefs = mutableMapOf, C>() +//// TODO: Do not know how to make it without context receivers +//context(LabeledPolynomialSpace>) +//@Suppress("FunctionName") +//public fun LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) // -// // Cleaning the degrees, summing monomials of the same degrees. -// for (entry in pairs) { -// val key = entry.first.cleanUp() -// val value = entry.second -// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value -// } +//context(LabeledPolynomialSpace>) +//@Suppress("FunctionName") +//public fun LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) // -// // Removing zero monomials. -// return LabeledPolynomial( -// fixedCoefs.filterValues { it.isNotZero() } -// ) -//} -///** -// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received -// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. -// * -// * @param coefs Coefficients of the instants. -// * -// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. -// */ -//context(A) -//fun > LabeledPolynomial(coefs: Map, C>): LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) -///** -// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received -// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. -// * -// * @param pairs Collection of pairs that represents monomials. -// * -// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. -// */ -//context(A) -//fun > LabeledPolynomial(pairs: Collection, C>>): LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) -///** -// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received -// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. -// * -// * @param pairs Collection of pairs that represents monomials. -// * -// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. -// */ -//context(A) -//fun > LabeledPolynomial(vararg pairs: Pair, C>): LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) -///** -// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received -// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. -// * -// * @param pairs Collection of pairs that represent monomials. -// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. -// * -// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. -// */ -//context(LabeledPolynomialSpace) -//internal fun > LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true): LabeledPolynomial { -// if (!toCheckInput) return LabeledPolynomial(coefs) +//context(LabeledPolynomialSpace>) +//@Suppress("FunctionName") +//public fun LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(pairs.toList(), toCheckInput = true) // -// // Map for cleaned coefficients. -// val fixedCoefs = mutableMapOf, C>() -// -// // Cleaning the degrees, summing monomials of the same degrees. -// for (entry in coefs) { -// val key = entry.key.cleanUp() -// val value = entry.value -// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value -// } -// -// // Removing zero monomials. -// return LabeledPolynomial( -// fixedCoefs -// .filter { it.value.isNotZero() } -// ) -//} -///** -// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received -// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. -// * -// * @param pairs Collection of pairs that represent monomials. -// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. -// * -// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. -// */ -//context(LabeledPolynomialSpace) -//internal fun > LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean): LabeledPolynomial { -// if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) -// -// // Map for cleaned coefficients. -// val fixedCoefs = mutableMapOf, C>() -// -// // Cleaning the degrees, summing monomials of the same degrees. -// for (entry in pairs) { -// val key = entry.first.cleanUp() -// val value = entry.second -// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value -// } -// -// // Removing zero monomials. -// return LabeledPolynomial( -// fixedCoefs.filterValues { it.isNotZero() } -// ) -//} -///** -// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received -// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. -// * -// * @param pairs Collection of pairs that represents monomials. -// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. -// * -// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. -// */ -//context(LabeledPolynomialSpace) -//internal fun > LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean): LabeledPolynomial { -// if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) -// -// // Map for cleaned coefficients. -// val fixedCoefs = mutableMapOf, C>() -// -// // Cleaning the degrees, summing monomials of the same degrees. -// for (entry in pairs) { -// val key = entry.first.cleanUp() -// val value = entry.second -// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value -// } -// -// // Removing zero monomials. -// return LabeledPolynomial( -// fixedCoefs.filterValues { it.isNotZero() } -// ) -//} -///** -// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received -// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. -// * -// * @param coefs Coefficients of the instants. -// * -// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial(coefs: Map, C>): LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) -///** -// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received -// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. -// * -// * @param pairs Collection of pairs that represents monomials. -// * -// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial(pairs: Collection, C>>): LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) -///** -// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from keys of received -// * map, sums up proportional monomials, removes aero monomials, and if result is zero map adds only element in it. -// * -// * @param pairs Collection of pairs that represents monomials. -// * -// * @throws LabeledPolynomialError If no coefficient received or if any of degrees in any monomial is negative. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial(vararg pairs: Pair, C>): LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) -// -//fun C.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to this)) -// -//context(A) -//fun > Variable.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1U) to one)) -// -//context(LabeledPolynomialSpace) -//fun > Variable.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1U) to constantOne)) -// -//context(A) -//fun > Variable.asLabeledPolynomial(c: C) : LabeledPolynomial = -// if(c.isZero()) LabeledPolynomial(emptyMap()) -// else LabeledPolynomial(mapOf(mapOf(this to 1U) to c)) -// -//context(LabeledPolynomialSpace) -//fun > Variable.asLabeledPolynomial(c: C) : LabeledPolynomial = -// if(c.isZero()) zero -// else LabeledPolynomial(mapOf(mapOf(this to 1U) to c)) +//context(LabeledPolynomialSpace>) +//public fun Variable.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to constantOne)) + +public fun C.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to this)) // endregion diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index 86c76949b..a1033fcc4 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -72,100 +72,10 @@ internal fun List.cleanUp() = subList(0, indexOfLast { it != 0U } + 1) // endregion // region Constructors and converters -// Waiting for context receivers :( TODO: Replace with context receivers when they will be available -//context(A) +//context(NumberedPolynomialSpace>) //@Suppress("FunctionName") -//internal fun > NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean): NumberedPolynomial { -// if (!toCheckInput) return NumberedPolynomial(coefs) -// -// val fixedCoefs = mutableMapOf, C>() -// -// for (entry in coefs) { -// val key = entry.key.cleanUp() -// val value = entry.value -// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value -// } -// -// return NumberedPolynomial( -// fixedCoefs -// .filter { it.value.isNotZero() } -// ) -//} -///** -// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received -// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. -// * -// * @param pairs Collection of pairs that represent monomials. -// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. -// * -// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. -// */ -//context(A) -//@Suppress("FunctionName") -//internal fun > NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean): NumberedPolynomial { -// if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) -// -// val fixedCoefs = mutableMapOf, C>() -// -// for (entry in pairs) { -// val key = entry.first.cleanUp() -// val value = entry.second -// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value -// } -// -// return NumberedPolynomial( -// fixedCoefs -// .filter { it.value.isNotZero() } -// ) -//} -///** -// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received -// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. -// * -// * @param pairs Collection of pairs that represent monomials. -// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. -// * -// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. -// */ -//context(A) -//@Suppress("FunctionName") -//internal fun > NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean): NumberedPolynomial = -// NumberedPolynomial(pairs.toMap(), toCheckInput) -///** -// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received -// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. -// * -// * @param coefs Coefficients of the instants. -// * -// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. -// */ -//context(A) -//public fun > NumberedPolynomial(coefs: Map, C>) = NumberedPolynomial(coefs, toCheckInput = true) -///** -// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received -// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. -// * -// * @param pairs Collection of pairs that represent monomials. -// * -// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. -// */ -//context(A) -//public fun > NumberedPolynomial(pairs: Collection, C>>) = NumberedPolynomial(pairs, toCheckInput = true) -///** -// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received -// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. -// * -// * @param pairs Collection of pairs that represent monomials. -// * -// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. -// */ -//context(A) -//public fun > NumberedPolynomial(vararg pairs: Pair, C>) = NumberedPolynomial(*pairs, toCheckInput = true) -// -//context(NumberedPolynomialSpace) -//@Suppress("FunctionName") -//internal fun > NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean): NumberedPolynomial { +//internal fun NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = false) : NumberedPolynomial { // if (!toCheckInput) return NumberedPolynomial(coefs) // // val fixedCoefs = mutableMapOf, C>() @@ -176,23 +86,14 @@ internal fun List.cleanUp() = subList(0, indexOfLast { it != 0U } + 1) // fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value // } // -// return NumberedPolynomial( -// fixedCoefs -// .filter { it.value.isNotZero() } +// return NumberedPolynomial( +// fixedCoefs.filterValues { it.isNotZero() } // ) //} -///** -// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received -// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. -// * -// * @param pairs Collection of pairs that represent monomials. -// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. -// * -// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. -// */ -//context(NumberedPolynomialSpace) +// +//context(NumberedPolynomialSpace>) //@Suppress("FunctionName") -//internal fun > NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean): NumberedPolynomial { +//internal fun NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = false) : NumberedPolynomial { // if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) // // val fixedCoefs = mutableMapOf, C>() @@ -203,56 +104,25 @@ internal fun List.cleanUp() = subList(0, indexOfLast { it != 0U } + 1) // fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value // } // -// return NumberedPolynomial( -// fixedCoefs -// .filter { it.value.isNotZero() } +// return NumberedPolynomial( +// fixedCoefs.filterValues { it.isNotZero() } // ) //} -///** -// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received -// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. -// * -// * @param pairs Collection of pairs that represent monomials. -// * @param toCheckInput If it's `true` cleaning of [coefficients] is executed otherwise it is not. -// * -// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. -// */ -//context(NumberedPolynomialSpace) +// +//// TODO: Do not know how to make it without context receivers +//context(NumberedPolynomialSpace>) //@Suppress("FunctionName") -//internal fun > NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean): NumberedPolynomial = -// NumberedPolynomial(pairs.toList(), toCheckInput) -///** -// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received -// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. -// * -// * @param coefs Coefficients of the instants. -// * -// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial(coefs: Map, C>) = NumberedPolynomial(coefs, toCheckInput = true) -///** -// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received -// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. -// * -// * @param pairs Collection of pairs that represent monomials. -// * -// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial(pairs: Collection, C>>) = NumberedPolynomial(pairs, toCheckInput = true) -///** -// * Gets the coefficients in format of [coefficients] field and cleans it: removes zero degrees from end of received -// * lists, sums up proportional monomials, removes zero monomials, and if result is empty map adds only element in it. -// * -// * @param pairs Collection of pairs that represent monomials. -// * -// * @throws PolynomialError If no coefficient received or if any of degrees in any monomial is negative. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial(vararg pairs: Pair, C>) = NumberedPolynomial(*pairs, toCheckInput = true) +//public fun NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) +// +//context(NumberedPolynomialSpace>) +//@Suppress("FunctionName") +//public fun NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) +// +//context(NumberedPolynomialSpace>) +//@Suppress("FunctionName") +//public fun NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(pairs.toList(), toCheckInput = true) -public fun > C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(emptyList() to this)) +public fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(emptyList() to this)) // endregion @@ -314,7 +184,7 @@ public open class NumberedPolynomialSpace>( */ public override operator fun NumberedPolynomial.times(other: Int): NumberedPolynomial = if (other == 0) zero - else NumberedPolynomial( + else NumberedPolynomial( coefficients .applyAndRemoveZeros { mapValues { (_, c) -> c * other } @@ -707,4 +577,51 @@ public open class NumberedPolynomialSpace>( } } // endregion + + // region Constructors and converters + + @Suppress("FunctionName") + internal fun NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = false) : NumberedPolynomial { + if (!toCheckInput) return NumberedPolynomial(coefs) + + val fixedCoefs = mutableMapOf, C>() + + for (entry in coefs) { + val key = entry.key.cleanUp() + val value = entry.value + fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value + } + + return NumberedPolynomial( + fixedCoefs.filterValues { it.isNotZero() } + ) + } + + @Suppress("FunctionName") + internal fun NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = false) : NumberedPolynomial { + if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) + + val fixedCoefs = mutableMapOf, C>() + + for (entry in pairs) { + val key = entry.first.cleanUp() + val value = entry.second + fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value + } + + return NumberedPolynomial( + fixedCoefs.filterValues { it.isNotZero() } + ) + } + + @Suppress("FunctionName") + public fun NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) + + @Suppress("FunctionName") + public fun NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) + + @Suppress("FunctionName") + public fun NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(pairs.toList(), toCheckInput = true) + + // endregion } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 1ac413818..2f7976da6 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -14,7 +14,32 @@ import kotlin.math.min * * @param coefficients constant is the leftmost coefficient. */ -public data class Polynomial(public val coefficients: List) : AbstractPolynomial { +public data class Polynomial( + /** + * List that collects coefficients of the polynomial. Every monomial `a x^d` is represented as a coefficients + * `a` placed into the list with index `d`. For example coefficients of 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 recommended not to put extra zeros at end of the list (as for `0x^3` and `0x^4` in the example), but is not + * prohibited. + */ + public val coefficients: List +) : AbstractPolynomial { override fun toString(): String = "Polynomial$coefficients" } -- 2.34.1 From bb5e638b31186607bf953bff3bd2f5275f13e0c1 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 15 Mar 2022 20:38:27 +0300 Subject: [PATCH 030/275] Added polynomial spaces and scopes fabrics --- .../kmath/functions/labeledPolynomialUtil.kt | 189 +----------------- .../kmath/functions/numberedPolynomialUtil.kt | 189 +----------------- 2 files changed, 20 insertions(+), 358 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt index 9cf4f2652..5689f6e1b 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt @@ -54,7 +54,7 @@ import kotlin.contracts.* // else -> multiplyWithPowerInternalLogic(base, arg, pow) // } // -//// Trivial but slow as duck +//// Trivial but very slow //context(LabeledPolynomialSpace) //internal tailrec fun > multiplyWithPowerInternalLogic(base: LabeledPolynomial, arg: LabeledPolynomial, exponent: UInt): LabeledPolynomial = // when { @@ -71,7 +71,15 @@ import kotlin.contracts.* // region Utilities -// TODO: Docs +/** + * Crates a [LabeledPolynomialSpace] over received ring. + */ +public fun > A.labeledPolynomial(): LabeledPolynomialSpace = + LabeledPolynomialSpace(this) + +/** + * Crates a [LabeledPolynomialSpace]'s scope over received ring. + */ @OptIn(ExperimentalContracts::class) public inline fun , R> A.labeledPolynomial(block: LabeledPolynomialSpace.() -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } @@ -254,64 +262,6 @@ public inline fun , R> A.labeledPolynomial(block: LabeledPolynomi //// region Field case // -//operator fun > Polynomial.div(other: Polynomial): Polynomial { -// if (other.isZero()) throw ArithmeticException("/ by zero") -// if (isZero()) return this -// -// fun Map, T>.leadingTerm() = -// this -// .asSequence() -// .map { Pair(it.key, it.value) } -// .reduce { (accDegs, accC), (listDegs, listC) -> -// for (i in 0..accDegs.lastIndex) { -// if (accDegs[i] > listDegs.getOrElse(i) { 0 }) return@reduce accDegs to accC -// if (accDegs[i] < listDegs.getOrElse(i) { 0 }) return@reduce listDegs to listC -// } -// if (accDegs.size < listDegs.size) listDegs to listC else accDegs to accC -// } -// -// var thisCoefficients = coefficients.toMutableMap() -// val otherCoefficients = other.coefficients -// val quotientCoefficients = HashMap, T>() -// -// var (thisLeadingTermDegs, thisLeadingTermC) = thisCoefficients.leadingTerm() -// val (otherLeadingTermDegs, otherLeadingTermC) = otherCoefficients.leadingTerm() -// -// while ( -// thisLeadingTermDegs.size >= otherLeadingTermDegs.size && -// (0..otherLeadingTermDegs.lastIndex).all { thisLeadingTermDegs[it] >= otherLeadingTermDegs[it] } -// ) { -// val multiplierDegs = -// thisLeadingTermDegs -// .mapIndexed { index, deg -> deg - otherLeadingTermDegs.getOrElse(index) { 0 } } -// .cleanUp() -// val multiplierC = thisLeadingTermC / otherLeadingTermC -// -// quotientCoefficients[multiplierDegs] = multiplierC -// -// for ((degs, t) in otherCoefficients) { -// val productDegs = -// (0..max(degs.lastIndex, multiplierDegs.lastIndex)) -// .map { degs.getOrElse(it) { 0 } + multiplierDegs.getOrElse(it) { 0 } } -// .cleanUp() -// val productC = t * multiplierC -// thisCoefficients[productDegs] = -// if (productDegs in thisCoefficients) thisCoefficients[productDegs]!! - productC else -productC -// } -// -// thisCoefficients = thisCoefficients.filterValues { it.isNotZero() }.toMutableMap() -// -// if (thisCoefficients.isEmpty()) -// return Polynomial(quotientCoefficients, toCheckInput = false) -// -// val t = thisCoefficients.leadingTerm() -// thisLeadingTermDegs = t.first -// thisLeadingTermC = t.second -// } -// -// return Polynomial(quotientCoefficients, toCheckInput = false) -//} -// //operator fun > Polynomial.div(other: T): Polynomial = // if (other.isZero()) throw ArithmeticException("/ by zero") // else @@ -321,125 +271,6 @@ public inline fun , R> A.labeledPolynomial(block: LabeledPolynomi // toCheckInput = false // ) // -//operator fun > Polynomial.rem(other: Polynomial): Polynomial { -// if (other.isZero()) throw ArithmeticException("/ by zero") -// if (isZero()) return this -// -// fun Map, T>.leadingTerm() = -// this -// .asSequence() -// .map { Pair(it.key, it.value) } -// .reduce { (accDegs, accC), (listDegs, listC) -> -// for (i in 0..accDegs.lastIndex) { -// if (accDegs[i] > listDegs.getOrElse(i) { 0 }) return@reduce accDegs to accC -// if (accDegs[i] < listDegs.getOrElse(i) { 0 }) return@reduce listDegs to listC -// } -// if (accDegs.size < listDegs.size) listDegs to listC else accDegs to accC -// } -// -// var thisCoefficients = coefficients.toMutableMap() -// val otherCoefficients = other.coefficients -// -// var (thisLeadingTermDegs, thisLeadingTermC) = thisCoefficients.leadingTerm() -// val (otherLeadingTermDegs, otherLeadingTermC) = otherCoefficients.leadingTerm() -// -// while ( -// thisLeadingTermDegs.size >= otherLeadingTermDegs.size && -// (0..otherLeadingTermDegs.lastIndex).all { thisLeadingTermDegs[it] >= otherLeadingTermDegs[it] } -// ) { -// val multiplierDegs = -// thisLeadingTermDegs -// .mapIndexed { index, deg -> deg - otherLeadingTermDegs.getOrElse(index) { 0 } } -// .cleanUp() -// val multiplierC = thisLeadingTermC / otherLeadingTermC -// -// for ((degs, t) in otherCoefficients) { -// val productDegs = -// (0..max(degs.lastIndex, multiplierDegs.lastIndex)) -// .map { degs.getOrElse(it) { 0 } + multiplierDegs.getOrElse(it) { 0 } } -// .cleanUp() -// val productC = t * multiplierC -// thisCoefficients[productDegs] = -// if (productDegs in thisCoefficients) thisCoefficients[productDegs]!! - productC else -productC -// } -// -// thisCoefficients = thisCoefficients.filterValues { it.isNotZero() }.toMutableMap() -// -// if (thisCoefficients.isEmpty()) -// return Polynomial(thisCoefficients, toCheckInput = false) -// -// val t = thisCoefficients.leadingTerm() -// thisLeadingTermDegs = t.first -// thisLeadingTermC = t.second -// } -// -// return Polynomial(thisCoefficients, toCheckInput = false) -//} -// -//infix fun > Polynomial.divrem(other: Polynomial): Polynomial.Companion.DividingResult { -// if (other.isZero()) throw ArithmeticException("/ by zero") -// if (isZero()) return Polynomial.Companion.DividingResult(this, this) -// -// fun Map, T>.leadingTerm() = -// this -// .asSequence() -// .map { Pair(it.key, it.value) } -// .reduce { (accDegs, accC), (listDegs, listC) -> -// for (i in 0..accDegs.lastIndex) { -// if (accDegs[i] > listDegs.getOrElse(i) { 0 }) return@reduce accDegs to accC -// if (accDegs[i] < listDegs.getOrElse(i) { 0 }) return@reduce listDegs to listC -// } -// if (accDegs.size < listDegs.size) listDegs to listC else accDegs to accC -// } -// -// var thisCoefficients = coefficients.toMutableMap() -// val otherCoefficients = other.coefficients -// val quotientCoefficients = HashMap, T>() -// -// var (thisLeadingTermDegs, thisLeadingTermC) = thisCoefficients.leadingTerm() -// val (otherLeadingTermDegs, otherLeadingTermC) = otherCoefficients.leadingTerm() -// -// while ( -// thisLeadingTermDegs.size >= otherLeadingTermDegs.size && -// (0..otherLeadingTermDegs.lastIndex).all { thisLeadingTermDegs[it] >= otherLeadingTermDegs[it] } -// ) { -// val multiplierDegs = -// thisLeadingTermDegs -// .mapIndexed { index, deg -> deg - otherLeadingTermDegs.getOrElse(index) { 0 } } -// .cleanUp() -// val multiplierC = thisLeadingTermC / otherLeadingTermC -// -// quotientCoefficients[multiplierDegs] = multiplierC -// -// for ((degs, t) in otherCoefficients) { -// val productDegs = -// (0..max(degs.lastIndex, multiplierDegs.lastIndex)) -// .map { degs.getOrElse(it) { 0 } + multiplierDegs.getOrElse(it) { 0 } } -// .cleanUp() -// val productC = t * multiplierC -// thisCoefficients[productDegs] = -// if (productDegs in thisCoefficients) thisCoefficients[productDegs]!! - productC else -productC -// } -// -// thisCoefficients = thisCoefficients.filterValues { it.isNotZero() }.toMutableMap() -// -// if (thisCoefficients.isEmpty()) -// return Polynomial.Companion.DividingResult( -// Polynomial(quotientCoefficients, toCheckInput = false), -// Polynomial(thisCoefficients, toCheckInput = false) -// ) -// -// val t = thisCoefficients.leadingTerm() -// thisLeadingTermDegs = t.first -// thisLeadingTermC = t.second -// } -// -// return Polynomial.Companion.DividingResult( -// Polynomial(quotientCoefficients, toCheckInput = false), -// Polynomial(thisCoefficients, toCheckInput = false) -// ) -//} -// //// endregion // endregion diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt index b7620e792..de95d0151 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt @@ -38,7 +38,7 @@ import kotlin.jvm.JvmName // else -> multiplyWithPowerInternalLogic(base, arg, pow) // } // -//// Trivial but slow as duck +//// Trivial but very slow //context(NumberedPolynomialSpace) //internal tailrec fun > multiplyWithPowerInternalLogic(base: NumberedPolynomial, arg: NumberedPolynomial, exponent: UInt): NumberedPolynomial = // when { @@ -55,7 +55,15 @@ import kotlin.jvm.JvmName // region Utilities -// TODO: Docs +/** + * Crates a [NumberedPolynomialSpace] over received ring. + */ +public fun > A.numberedPolynomial(): NumberedPolynomialSpace = + NumberedPolynomialSpace(this) + +/** + * Crates a [NumberedPolynomialSpace]'s scope over received ring. + */ @OptIn(ExperimentalContracts::class) public inline fun , R> A.numberedPolynomial(block: NumberedPolynomialSpace.() -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } @@ -282,64 +290,6 @@ public inline fun , R> A.numberedPolynomial(block: NumberedPolyno //// region Field case // -//operator fun > Polynomial.div(other: Polynomial): Polynomial { -// if (other.isZero()) throw ArithmeticException("/ by zero") -// if (isZero()) return this -// -// fun Map, T>.leadingTerm() = -// this -// .asSequence() -// .map { Pair(it.key, it.value) } -// .reduce { (accDegs, accC), (listDegs, listC) -> -// for (i in 0..accDegs.lastIndex) { -// if (accDegs[i] > listDegs.getOrElse(i) { 0 }) return@reduce accDegs to accC -// if (accDegs[i] < listDegs.getOrElse(i) { 0 }) return@reduce listDegs to listC -// } -// if (accDegs.size < listDegs.size) listDegs to listC else accDegs to accC -// } -// -// var thisCoefficients = coefficients.toMutableMap() -// val otherCoefficients = other.coefficients -// val quotientCoefficients = HashMap, T>() -// -// var (thisLeadingTermDegs, thisLeadingTermC) = thisCoefficients.leadingTerm() -// val (otherLeadingTermDegs, otherLeadingTermC) = otherCoefficients.leadingTerm() -// -// while ( -// thisLeadingTermDegs.size >= otherLeadingTermDegs.size && -// (0..otherLeadingTermDegs.lastIndex).all { thisLeadingTermDegs[it] >= otherLeadingTermDegs[it] } -// ) { -// val multiplierDegs = -// thisLeadingTermDegs -// .mapIndexed { index, deg -> deg - otherLeadingTermDegs.getOrElse(index) { 0 } } -// .cleanUp() -// val multiplierC = thisLeadingTermC / otherLeadingTermC -// -// quotientCoefficients[multiplierDegs] = multiplierC -// -// for ((degs, t) in otherCoefficients) { -// val productDegs = -// (0..max(degs.lastIndex, multiplierDegs.lastIndex)) -// .map { degs.getOrElse(it) { 0 } + multiplierDegs.getOrElse(it) { 0 } } -// .cleanUp() -// val productC = t * multiplierC -// thisCoefficients[productDegs] = -// if (productDegs in thisCoefficients) thisCoefficients[productDegs]!! - productC else -productC -// } -// -// thisCoefficients = thisCoefficients.filterValues { it.isNotZero() }.toMutableMap() -// -// if (thisCoefficients.isEmpty()) -// return Polynomial(quotientCoefficients, toCheckInput = false) -// -// val t = thisCoefficients.leadingTerm() -// thisLeadingTermDegs = t.first -// thisLeadingTermC = t.second -// } -// -// return Polynomial(quotientCoefficients, toCheckInput = false) -//} -// //operator fun > Polynomial.div(other: T): Polynomial = // if (other.isZero()) throw ArithmeticException("/ by zero") // else @@ -349,125 +299,6 @@ public inline fun , R> A.numberedPolynomial(block: NumberedPolyno // toCheckInput = false // ) // -//operator fun > Polynomial.rem(other: Polynomial): Polynomial { -// if (other.isZero()) throw ArithmeticException("/ by zero") -// if (isZero()) return this -// -// fun Map, T>.leadingTerm() = -// this -// .asSequence() -// .map { Pair(it.key, it.value) } -// .reduce { (accDegs, accC), (listDegs, listC) -> -// for (i in 0..accDegs.lastIndex) { -// if (accDegs[i] > listDegs.getOrElse(i) { 0 }) return@reduce accDegs to accC -// if (accDegs[i] < listDegs.getOrElse(i) { 0 }) return@reduce listDegs to listC -// } -// if (accDegs.size < listDegs.size) listDegs to listC else accDegs to accC -// } -// -// var thisCoefficients = coefficients.toMutableMap() -// val otherCoefficients = other.coefficients -// -// var (thisLeadingTermDegs, thisLeadingTermC) = thisCoefficients.leadingTerm() -// val (otherLeadingTermDegs, otherLeadingTermC) = otherCoefficients.leadingTerm() -// -// while ( -// thisLeadingTermDegs.size >= otherLeadingTermDegs.size && -// (0..otherLeadingTermDegs.lastIndex).all { thisLeadingTermDegs[it] >= otherLeadingTermDegs[it] } -// ) { -// val multiplierDegs = -// thisLeadingTermDegs -// .mapIndexed { index, deg -> deg - otherLeadingTermDegs.getOrElse(index) { 0 } } -// .cleanUp() -// val multiplierC = thisLeadingTermC / otherLeadingTermC -// -// for ((degs, t) in otherCoefficients) { -// val productDegs = -// (0..max(degs.lastIndex, multiplierDegs.lastIndex)) -// .map { degs.getOrElse(it) { 0 } + multiplierDegs.getOrElse(it) { 0 } } -// .cleanUp() -// val productC = t * multiplierC -// thisCoefficients[productDegs] = -// if (productDegs in thisCoefficients) thisCoefficients[productDegs]!! - productC else -productC -// } -// -// thisCoefficients = thisCoefficients.filterValues { it.isNotZero() }.toMutableMap() -// -// if (thisCoefficients.isEmpty()) -// return Polynomial(thisCoefficients, toCheckInput = false) -// -// val t = thisCoefficients.leadingTerm() -// thisLeadingTermDegs = t.first -// thisLeadingTermC = t.second -// } -// -// return Polynomial(thisCoefficients, toCheckInput = false) -//} -// -//infix fun > Polynomial.divrem(other: Polynomial): Polynomial.Companion.DividingResult { -// if (other.isZero()) throw ArithmeticException("/ by zero") -// if (isZero()) return Polynomial.Companion.DividingResult(this, this) -// -// fun Map, T>.leadingTerm() = -// this -// .asSequence() -// .map { Pair(it.key, it.value) } -// .reduce { (accDegs, accC), (listDegs, listC) -> -// for (i in 0..accDegs.lastIndex) { -// if (accDegs[i] > listDegs.getOrElse(i) { 0 }) return@reduce accDegs to accC -// if (accDegs[i] < listDegs.getOrElse(i) { 0 }) return@reduce listDegs to listC -// } -// if (accDegs.size < listDegs.size) listDegs to listC else accDegs to accC -// } -// -// var thisCoefficients = coefficients.toMutableMap() -// val otherCoefficients = other.coefficients -// val quotientCoefficients = HashMap, T>() -// -// var (thisLeadingTermDegs, thisLeadingTermC) = thisCoefficients.leadingTerm() -// val (otherLeadingTermDegs, otherLeadingTermC) = otherCoefficients.leadingTerm() -// -// while ( -// thisLeadingTermDegs.size >= otherLeadingTermDegs.size && -// (0..otherLeadingTermDegs.lastIndex).all { thisLeadingTermDegs[it] >= otherLeadingTermDegs[it] } -// ) { -// val multiplierDegs = -// thisLeadingTermDegs -// .mapIndexed { index, deg -> deg - otherLeadingTermDegs.getOrElse(index) { 0 } } -// .cleanUp() -// val multiplierC = thisLeadingTermC / otherLeadingTermC -// -// quotientCoefficients[multiplierDegs] = multiplierC -// -// for ((degs, t) in otherCoefficients) { -// val productDegs = -// (0..max(degs.lastIndex, multiplierDegs.lastIndex)) -// .map { degs.getOrElse(it) { 0 } + multiplierDegs.getOrElse(it) { 0 } } -// .cleanUp() -// val productC = t * multiplierC -// thisCoefficients[productDegs] = -// if (productDegs in thisCoefficients) thisCoefficients[productDegs]!! - productC else -productC -// } -// -// thisCoefficients = thisCoefficients.filterValues { it.isNotZero() }.toMutableMap() -// -// if (thisCoefficients.isEmpty()) -// return Polynomial.Companion.DividingResult( -// Polynomial(quotientCoefficients, toCheckInput = false), -// Polynomial(thisCoefficients, toCheckInput = false) -// ) -// -// val t = thisCoefficients.leadingTerm() -// thisLeadingTermDegs = t.first -// thisLeadingTermC = t.second -// } -// -// return Polynomial.Companion.DividingResult( -// Polynomial(quotientCoefficients, toCheckInput = false), -// Polynomial(thisCoefficients, toCheckInput = false) -// ) -//} -// //// endregion // endregion -- 2.34.1 From 16cf1bc65e6cd1a2955c9ca3bf5e4200eae71c71 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Wed, 16 Mar 2022 00:47:07 +0300 Subject: [PATCH 031/275] Implemented all derivative-like functions --- .../kmath/functions/labeledPolynomialUtil.kt | 253 ++++++++++++++++- .../kmath/functions/numberedPolynomialUtil.kt | 255 +++++++++++------- .../kmath/functions/polynomialUtil.kt | 2 +- 3 files changed, 407 insertions(+), 103 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt index 5689f6e1b..544cca410 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt @@ -5,8 +5,10 @@ package space.kscience.kmath.functions +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* import kotlin.contracts.* +import kotlin.math.max // TODO: Docs @@ -321,6 +323,251 @@ public inline fun , R> A.labeledPolynomial(block: LabeledPolynomi // //// endregion -//// region Algebraic derivative and antiderivative -//// TODO -//// endregion \ No newline at end of file +// region Algebraic derivative and antiderivative + +/** + * Returns algebraic derivative of received polynomial. + */ +@UnstableKMathAPI +public fun > LabeledPolynomial.derivativeWithRespectTo( + algebra: A, + variable: Variable, +): LabeledPolynomial = algebra { + LabeledPolynomial( + buildMap(coefficients.size) { + 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) + } + } + }, + optimizedMultiply(c, degs[variable]!!) + ) + } + } + ) +} + +/** + * Returns algebraic derivative of received polynomial. + */ +@UnstableKMathAPI +public fun > LabeledPolynomial.derivativeWithRespectTo( + algebra: A, + variables: Collection, +): LabeledPolynomial = algebra { + val cleanedVariables = variables.toSet() + if (cleanedVariables.isEmpty()) return this@derivativeWithRespectTo + LabeledPolynomial( + buildMap(coefficients.size) { + coefficients + .forEach { (degs, c) -> + if (!degs.keys.containsAll(cleanedVariables)) return@forEach + put( + buildMap { + degs.forEach { (vari, deg) -> + when { + vari !in cleanedVariables -> put(vari, deg) + deg > 1u -> put(vari, deg - 1u) + } + } + }, + cleanedVariables.fold(c) { acc, variable -> optimizedMultiply(acc, degs[variable]!!) } + ) + } + } + ) +} + +/** + * Returns algebraic derivative of received polynomial. + */ +@UnstableKMathAPI +public fun > LabeledPolynomial.nthDerivativeWithRespectTo( + algebra: A, + variable: Variable, + order: UInt +): LabeledPolynomial = algebra { + if (order == 0u) return this@nthDerivativeWithRespectTo + LabeledPolynomial( + buildMap(coefficients.size) { + 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 -> optimizedMultiply(acc, ord) } + } + ) + } + } + ) +} + +/** + * Returns algebraic derivative of received polynomial. + */ +@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.size) { + 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 -> optimizedMultiply(acc2, ord) } + } + } + ) + } + } + ) +} + +/** + * Returns algebraic antiderivative of received polynomial. + */ +@UnstableKMathAPI +public fun > LabeledPolynomial.antiderivativeWithRespectTo( + algebra: A, + variable: Variable, +): LabeledPolynomial = algebra { + LabeledPolynomial( + buildMap(coefficients.size) { + coefficients + .forEach { (degs, c) -> + val newDegs = buildMap(degs.size + 1) { + put(variable, 1u) + for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) + } + put( + newDegs, + c / optimizedMultiply(one, newDegs[variable]!!) + ) + } + } + ) +} + +/** + * Returns algebraic antiderivative of received polynomial. + */ +@UnstableKMathAPI +public fun > LabeledPolynomial.antiderivativeWithRespectTo( + algebra: A, + variables: Collection, +): LabeledPolynomial = algebra { + val cleanedVariables = variables.toSet() + if (cleanedVariables.isEmpty()) return this@antiderivativeWithRespectTo + LabeledPolynomial( + buildMap(coefficients.size) { + coefficients + .forEach { (degs, c) -> + val newDegs = buildMap(degs.size + 1) { + for (variable in cleanedVariables) put(variable, 1u) + for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) + } + put( + newDegs, + cleanedVariables.fold(c) { acc, variable -> acc / optimizedMultiply(one, newDegs[variable]!!) } + ) + } + } + ) +} + +/** + * Returns algebraic derivative of received polynomial. + */ +@UnstableKMathAPI +public fun > LabeledPolynomial.nthAntiderivativeWithRespectTo( + algebra: A, + variable: Variable, + order: UInt +): LabeledPolynomial = algebra { + if (order == 0u) return this@nthAntiderivativeWithRespectTo + LabeledPolynomial( + buildMap(coefficients.size) { + coefficients + .forEach { (degs, c) -> + val newDegs = buildMap(degs.size + 1) { + put(variable, order) + for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) + } + put( + newDegs, + newDegs[variable]!!.let { deg -> + (deg downTo deg - order + 1u) + .fold(c) { acc, ord -> acc / optimizedMultiply(one, ord) } + } + ) + } + } + ) +} + +/** + * Returns algebraic derivative of received polynomial. + */ +@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 = buildMap(degs.size + 1) { + for ((variable, order) in filteredVariablesAndOrders) put(variable, order) + for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) + } + put( + newDegs, + filteredVariablesAndOrders.entries.fold(c) { acc1, (index, order) -> + newDegs[index]!!.let { deg -> + (deg downTo deg - order + 1u) + .fold(acc1) { acc2, ord -> acc2 / optimizedMultiply(one, ord) } + } + } + ) + } + } + ) +} + +// endregion \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt index de95d0151..47644b26a 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt @@ -4,7 +4,7 @@ import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* import kotlin.contracts.* import kotlin.jvm.JvmName - +import kotlin.math.max // TODO: Docs @@ -382,70 +382,51 @@ public fun > NumberedPolynomial.derivativeWithRespectTo( ): NumberedPolynomial = algebra { NumberedPolynomial( buildMap(coefficients.size) { - coefficients.forEach { (degs, c) -> - put( - degs.mapIndexed { index, deg -> - when { - index != variable -> deg - deg > 0u -> deg - 1u - else -> return@forEach - } - }, - optimizedMultiply(c, degs.getOrElse(variable) { 1u }.toInt()) - ) - } + coefficients + .forEach { (degs, c) -> + if (degs.size > variable) return@forEach + put( + degs.mapIndexed { index, deg -> + when { + index != variable -> deg + deg > 0u -> deg - 1u + else -> return@forEach + } + }.cleanUp(), + optimizedMultiply(c, degs[variable]) + ) + } } ) } /** * Returns algebraic derivative of received polynomial. - */ // TODO: This one does not work!!! -@UnstableKMathAPI -public fun > NumberedPolynomial.derivativeWithRespectTo( - algebra: A, - variables: IntArray, -): NumberedPolynomial = algebra { - NumberedPolynomial( - buildMap(coefficients.size) { - coefficients.forEach { (degs, c) -> - put( - degs.mapIndexed { index, deg -> - when { - index !in variables -> deg - deg > 0u -> deg - 1u - else -> return@forEach - } - }, - optimizedMultiply(c, variables.fold(1u) { acc, variable -> acc * degs.getOrElse(variable) { 1u } }.toInt()) - ) - } - } - ) -} - -/** - * Returns algebraic derivative of received polynomial. - */ // TODO: This one does not work!!! + */ @UnstableKMathAPI public fun > NumberedPolynomial.derivativeWithRespectTo( algebra: A, variables: Collection, ): NumberedPolynomial = algebra { + val cleanedVariables = variables.toSet() + if (cleanedVariables.isEmpty()) return this@derivativeWithRespectTo + val maxRespectedVariable = cleanedVariables.maxOrNull()!! NumberedPolynomial( buildMap(coefficients.size) { - coefficients.forEach { (degs, c) -> - put( - degs.mapIndexed { index, deg -> - when { - index !in variables -> deg - deg > 0u -> deg - 1u - else -> return@forEach - } - }, - optimizedMultiply(c, variables.fold(1u) { acc, variable -> acc * degs.getOrElse(variable) { 1u } }.toInt()) - ) - } + coefficients + .forEach { (degs, c) -> + if (degs.size > maxRespectedVariable) return@forEach + put( + degs.mapIndexed { index, deg -> + when { + index !in cleanedVariables -> deg + deg > 0u -> deg - 1u + else -> return@forEach + } + }.cleanUp(), + cleanedVariables.fold(c) { acc, variable -> optimizedMultiply(acc, degs[variable]) } + ) + } } ) } @@ -459,24 +440,60 @@ public fun > NumberedPolynomial.nthDerivativeWithRespectTo( variable: Int, order: UInt ): NumberedPolynomial = algebra { + if (order == 0u) return this@nthDerivativeWithRespectTo NumberedPolynomial( buildMap(coefficients.size) { - coefficients.forEach { (degs, c) -> - put( - degs.mapIndexed { index, deg -> - when { - index != variable -> deg - deg >= order -> deg - order - else -> return@forEach + coefficients + .forEach { (degs, c) -> + if (degs.size > 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 -> optimizedMultiply(acc, ord) } } - }, - degs.getOrElse(variable) { 1u }.toInt().let { - (0u until order).fold(c) { acc, ord -> - optimizedMultiply(acc, ord.toInt()) + ) + } + } + ) +} + +/** + * Returns algebraic derivative of received polynomial. + */ +@UnstableKMathAPI +public fun > NumberedPolynomial.nthDerivativeWithRespectTo( + algebra: A, + variablesAndOrders: Map, +): NumberedPolynomial = algebra { + 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.size > 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 -> optimizedMultiply(acc2, ord) } + } } - } - ) - } + ) + } } ) } @@ -491,52 +508,92 @@ public fun > NumberedPolynomial.antiderivativeWithRespectTo( ): NumberedPolynomial = algebra { NumberedPolynomial( buildMap(coefficients.size) { - coefficients.forEach { (degs, c) -> - put( - degs.mapIndexed { index, deg -> if(index != variable) deg else deg + 1u }, - c / optimizedMultiply(one, degs.getOrElse(variable) { 1u }.toInt()) - ) - } + coefficients + .forEach { (degs, c) -> + put( + List(max(variable + 1, degs.size)) { if (it != variable) degs[it] else degs[it] + 1u }, + c / optimizedMultiply(one, degs[variable]) + ) + } } ) } /** * Returns algebraic antiderivative of received polynomial. - */ // TODO: This one does not work!!! -@UnstableKMathAPI -public fun > NumberedPolynomial.antiderivativeWithRespectTo( - algebra: A, - variables: IntArray, -): NumberedPolynomial = algebra { - NumberedPolynomial( - buildMap(coefficients.size) { - coefficients.forEach { (degs, c) -> - put( - degs.mapIndexed { index, deg -> if(index !in variables) deg else deg + 1u }, - c / optimizedMultiply(one, variables.fold(1u) { acc, variable -> acc * degs.getOrElse(variable) { 1u } }.toInt()) - ) - } - } - ) -} - -/** - * Returns algebraic antiderivative of received polynomial. - */ // TODO: This one does not work!!! + */ @UnstableKMathAPI public fun > NumberedPolynomial.antiderivativeWithRespectTo( algebra: A, variables: Collection, ): NumberedPolynomial = algebra { + val cleanedVariables = variables.toSet() + if (cleanedVariables.isEmpty()) return this@antiderivativeWithRespectTo + val maxRespectedVariable = cleanedVariables.maxOrNull()!! NumberedPolynomial( buildMap(coefficients.size) { - coefficients.forEach { (degs, c) -> - put( - degs.mapIndexed { index, deg -> if(index !in variables) deg else deg + 1u }, - c / optimizedMultiply(one, variables.fold(1u) { acc, variable -> acc * degs.getOrElse(variable) { 1u } }.toInt()) - ) - } + coefficients + .forEach { (degs, c) -> + put( + List(max(maxRespectedVariable + 1, degs.size)) { if (it !in variables) degs[it] else degs[it] + 1u }, + cleanedVariables.fold(c) { acc, variable -> acc / optimizedMultiply(one, degs[variable]) } + ) + } + } + ) +} + +/** + * Returns algebraic derivative of received polynomial. + */ +@UnstableKMathAPI +public fun > NumberedPolynomial.nthAntiderivativeWithRespectTo( + algebra: A, + variable: Int, + order: UInt +): NumberedPolynomial = algebra { + if (order == 0u) return this@nthAntiderivativeWithRespectTo + NumberedPolynomial( + buildMap(coefficients.size) { + coefficients + .forEach { (degs, c) -> + put( + List(max(variable + 1, degs.size)) { if (it != variable) degs[it] else degs[it] + order }, + degs[variable].let { deg -> + (deg downTo deg - order + 1u) + .fold(c) { acc, ord -> acc / optimizedMultiply(one, ord) } + } + ) + } + } + ) +} + +/** + * Returns algebraic derivative of received polynomial. + */ +@UnstableKMathAPI +public fun > NumberedPolynomial.nthAntiderivativeWithRespectTo( + algebra: A, + variablesAndOrders: Map, +): NumberedPolynomial = algebra { + 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[it] + filteredVariablesAndOrders.getOrElse(it) { 0u } }, + filteredVariablesAndOrders.entries.fold(c) { acc1, (index, order) -> + degs[index].let { deg -> + (deg downTo deg - order + 1u) + .fold(acc1) { acc2, ord -> acc2 / optimizedMultiply(one, ord) } + } + } + ) + } } ) } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt index a41a6cbd6..9c8cc0090 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt @@ -138,7 +138,7 @@ public fun Polynomial.nthDerivative( algebra: A, order: UInt, ): Polynomial where A : Ring, A : NumericAlgebra = algebra { - Polynomial(coefficients.drop(order.toInt()).mapIndexed { index, c -> (1..order.toInt()).fold(c) { acc, i -> acc * number(index + i) } }) + Polynomial(coefficients.drop(order.toInt()).mapIndexed { index, c -> (index + 1..index + order.toInt()).fold(c) { acc, i -> acc * number(i) } }) } /** -- 2.34.1 From 9aa131a9c6c69145761bc63fdae436da01916634 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Wed, 16 Mar 2022 01:06:39 +0300 Subject: [PATCH 032/275] Replaced `Variable` in `Labeled...` by `Symbol` and deleted it --- .../kmath/functions/LabeledPolynomial.kt | 145 +++++++++--------- .../functions/LabeledRationalFunction.kt | 37 ++--- .../kscience/kmath/functions/Variable.kt | 38 ----- .../kmath/functions/labeledPolynomialUtil.kt | 64 ++++---- 4 files changed, 126 insertions(+), 158 deletions(-) delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Variable.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt index 56dad975d..4106371cc 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.functions +import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.operations.* import kotlin.contracts.InvocationKind import kotlin.contracts.contract @@ -40,9 +41,9 @@ internal constructor( * ) to (-6) * ) * ``` - * where `a`, `b` and `c` are corresponding [Variable] objects. + * where `a`, `b` and `c` are corresponding [Symbol] objects. */ - public val coefficients: Map, C> + public val coefficients: Map, C> ) : AbstractPolynomial { override fun toString(): String = "LabeledPolynomial$coefficients" } @@ -67,7 +68,7 @@ internal fun labeledPolynomialError(message: Any): Nothing = throw LabeledPolyno /** * Returns the same degrees description of the monomial, but without zero degrees. */ -internal fun Map.cleanUp() = filterValues { it > 0U } +internal fun Map.cleanUp() = filterValues { it > 0U } // endregion @@ -75,10 +76,10 @@ internal fun Map.cleanUp() = filterValues { it > 0U } //context(LabeledPolynomialSpace>) //@Suppress("FunctionName") -//internal fun LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = false) : LabeledPolynomial { +//internal fun LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = false) : LabeledPolynomial { // if (!toCheckInput) return LabeledPolynomial(coefs) // -// val fixedCoefs = mutableMapOf, C>() +// val fixedCoefs = mutableMapOf, C>() // // for (entry in coefs) { // val key = entry.key.cleanUp() @@ -93,10 +94,10 @@ internal fun Map.cleanUp() = filterValues { it > 0U } // //context(LabeledPolynomialSpace>) //@Suppress("FunctionName") -//internal fun LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = false) : LabeledPolynomial { +//internal fun LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = false) : LabeledPolynomial { // if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) // -// val fixedCoefs = mutableMapOf, C>() +// val fixedCoefs = mutableMapOf, C>() // // for (entry in pairs) { // val key = entry.first.cleanUp() @@ -112,20 +113,20 @@ internal fun Map.cleanUp() = filterValues { it > 0U } //// TODO: Do not know how to make it without context receivers //context(LabeledPolynomialSpace>) //@Suppress("FunctionName") -//public fun LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) +//public fun LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) // //context(LabeledPolynomialSpace>) //@Suppress("FunctionName") -//public fun LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) +//public fun LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) // //context(LabeledPolynomialSpace>) //@Suppress("FunctionName") -//public fun LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(pairs.toList(), toCheckInput = true) +//public fun LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(pairs.toList(), toCheckInput = true) // //context(LabeledPolynomialSpace>) -//public fun Variable.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to constantOne)) +//public fun Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to constantOne)) -public fun C.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to this)) +public fun C.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to this)) // endregion @@ -140,24 +141,24 @@ public class LabeledPolynomialSpace>( public override val ring: A, ) : AbstractPolynomialSpaceOverRing, A> { - // region Variable-integer relation - public operator fun Variable.plus(other: Int): LabeledPolynomial = + // region Symbol-integer relation + public operator fun Symbol.plus(other: Int): LabeledPolynomial = if (other == 0) LabeledPolynomial(mapOf( mapOf(this@plus to 1U) to constantOne, )) else LabeledPolynomial(mapOf( mapOf(this@plus to 1U) to constantOne, - emptyMap() to constantOne * other, + emptyMap() to constantOne * other, )) - public operator fun Variable.minus(other: Int): LabeledPolynomial = + public operator fun Symbol.minus(other: Int): LabeledPolynomial = if (other == 0) LabeledPolynomial(mapOf( mapOf(this@minus to 1U) to -constantOne, )) else LabeledPolynomial(mapOf( mapOf(this@minus to 1U) to -constantOne, - emptyMap() to constantOne * other, + emptyMap() to constantOne * other, )) - public operator fun Variable.times(other: Int): LabeledPolynomial = + public operator fun Symbol.times(other: Int): LabeledPolynomial = if (other == 0) zero else LabeledPolynomial(mapOf( mapOf(this to 1U) to constantOne * other, @@ -165,23 +166,23 @@ public class LabeledPolynomialSpace>( // endregion // region Integer-variable relation - public operator fun Int.plus(other: Variable): LabeledPolynomial = + public operator fun Int.plus(other: Symbol): LabeledPolynomial = if (this == 0) LabeledPolynomial(mapOf( mapOf(other to 1U) to constantOne, )) else LabeledPolynomial(mapOf( mapOf(other to 1U) to constantOne, - emptyMap() to constantOne * this@plus, + emptyMap() to constantOne * this@plus, )) - public operator fun Int.minus(other: Variable): LabeledPolynomial = + public operator fun Int.minus(other: Symbol): LabeledPolynomial = if (this == 0) LabeledPolynomial(mapOf( mapOf(other to 1U) to -constantOne, )) else LabeledPolynomial(mapOf( mapOf(other to 1U) to -constantOne, - emptyMap() to constantOne * this@minus, + emptyMap() to constantOne * this@minus, )) - public operator fun Int.times(other: Variable): LabeledPolynomial = + public operator fun Int.times(other: Symbol): LabeledPolynomial = if (this == 0) zero else LabeledPolynomial(mapOf( mapOf(other to 1U) to constantOne * this@times, @@ -201,7 +202,7 @@ public class LabeledPolynomialSpace>( coefficients .toMutableMap() .apply { - val degs = emptyMap() + val degs = emptyMap() val result = getOrElse(degs) { constantZero } + other @@ -221,7 +222,7 @@ public class LabeledPolynomialSpace>( coefficients .toMutableMap() .apply { - val degs = emptyMap() + val degs = emptyMap() val result = getOrElse(degs) { constantZero } - other @@ -257,7 +258,7 @@ public class LabeledPolynomialSpace>( other.coefficients .toMutableMap() .apply { - val degs = emptyMap() + val degs = emptyMap() val result = this@plus + getOrElse(degs) { constantZero } @@ -277,7 +278,7 @@ public class LabeledPolynomialSpace>( other.coefficients .toMutableMap() .apply { - val degs = emptyMap() + val degs = emptyMap() val result = this@minus - getOrElse(degs) { constantZero } @@ -301,47 +302,47 @@ public class LabeledPolynomialSpace>( // endregion // region Constant-variable relation - public operator fun C.plus(other: Variable): LabeledPolynomial = + public operator fun C.plus(other: Symbol): LabeledPolynomial = if (isZero()) LabeledPolynomial(mapOf( mapOf(other to 1U) to constantOne, )) else LabeledPolynomial(mapOf( mapOf(other to 1U) to constantOne, - emptyMap() to this@plus, + emptyMap() to this@plus, )) - public operator fun C.minus(other: Variable): LabeledPolynomial = + public operator fun C.minus(other: Symbol): LabeledPolynomial = if (isZero()) LabeledPolynomial(mapOf( mapOf(other to 1U) to -constantOne, )) else LabeledPolynomial(mapOf( mapOf(other to 1U) to -constantOne, - emptyMap() to this@minus, + emptyMap() to this@minus, )) - public operator fun C.times(other: Variable): LabeledPolynomial = + public operator fun C.times(other: Symbol): LabeledPolynomial = if (isZero()) zero else LabeledPolynomial(mapOf( mapOf(other to 1U) to this@times, )) // endregion - // region Variable-constant relation - public operator fun Variable.plus(other: C): LabeledPolynomial = + // region Symbol-constant relation + public operator fun Symbol.plus(other: C): LabeledPolynomial = if (other.isZero()) LabeledPolynomial(mapOf( mapOf(this@plus to 1U) to constantOne, )) else LabeledPolynomial(mapOf( mapOf(this@plus to 1U) to constantOne, - emptyMap() to other, + emptyMap() to other, )) - public operator fun Variable.minus(other: C): LabeledPolynomial = + public operator fun Symbol.minus(other: C): LabeledPolynomial = if (other.isZero()) LabeledPolynomial(mapOf( mapOf(this@minus to 1U) to -constantOne, )) else LabeledPolynomial(mapOf( mapOf(this@minus to 1U) to -constantOne, - emptyMap() to other, + emptyMap() to other, )) - public operator fun Variable.times(other: C): LabeledPolynomial = + public operator fun Symbol.times(other: C): LabeledPolynomial = if (other.isZero()) zero else LabeledPolynomial(mapOf( mapOf(this@times to 1U) to other, @@ -355,11 +356,11 @@ public class LabeledPolynomialSpace>( override operator fun C.plus(other: LabeledPolynomial): LabeledPolynomial = if (this.isZero()) other else with(other.coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@plus)) + if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@plus)) else LabeledPolynomial( toMutableMap() .apply { - val degs = emptyMap() + val degs = emptyMap() val result = this@plus + getOrElse(degs) { constantZero } @@ -374,13 +375,13 @@ public class LabeledPolynomialSpace>( override operator fun C.minus(other: LabeledPolynomial): LabeledPolynomial = if (this.isZero()) other else with(other.coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@minus)) + if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@minus)) else LabeledPolynomial( toMutableMap() .apply { forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } - val degs = emptyMap() + val degs = emptyMap() val result = this@minus - getOrElse(degs) { constantZero } @@ -409,11 +410,11 @@ public class LabeledPolynomialSpace>( override operator fun LabeledPolynomial.plus(other: C): LabeledPolynomial = if (other.isZero()) this else with(coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to other)) + if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to other)) else LabeledPolynomial( toMutableMap() .apply { - val degs = emptyMap() + val degs = emptyMap() val result = getOrElse(degs) { constantZero } + other @@ -428,13 +429,13 @@ public class LabeledPolynomialSpace>( override operator fun LabeledPolynomial.minus(other: C): LabeledPolynomial = if (other.isZero()) this else with(coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to other)) + if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to other)) else LabeledPolynomial( toMutableMap() .apply { forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } - val degs = emptyMap() + val degs = emptyMap() val result = getOrElse(degs) { constantZero } - other @@ -456,8 +457,8 @@ public class LabeledPolynomialSpace>( ) // endregion - // region Variable-variable relation - public operator fun Variable.plus(other: Variable): LabeledPolynomial = + // region Symbol-variable relation + public operator fun Symbol.plus(other: Symbol): LabeledPolynomial = if (this == other) LabeledPolynomial(mapOf( mapOf(this to 1U) to constantOne * 2 )) @@ -465,13 +466,13 @@ public class LabeledPolynomialSpace>( mapOf(this to 1U) to constantOne, mapOf(other to 1U) to constantOne, )) - public operator fun Variable.minus(other: Variable): LabeledPolynomial = + public operator fun Symbol.minus(other: Symbol): LabeledPolynomial = if (this == other) zero else LabeledPolynomial(mapOf( mapOf(this to 1U) to constantOne, mapOf(other to 1U) to -constantOne, )) - public operator fun Variable.times(other: Variable): LabeledPolynomial = + public operator fun Symbol.times(other: Symbol): LabeledPolynomial = if (this == other) LabeledPolynomial(mapOf( mapOf(this to 2U) to constantOne )) @@ -480,8 +481,8 @@ public class LabeledPolynomialSpace>( )) // endregion - // region Variable-polynomial relation - public operator fun Variable.plus(other: LabeledPolynomial): LabeledPolynomial = + // region Symbol-polynomial relation + public operator fun Symbol.plus(other: LabeledPolynomial): LabeledPolynomial = with(other.coefficients) { if (isEmpty()) LabeledPolynomial(mapOf(mapOf(this@plus to 1u) to constantOne)) else LabeledPolynomial( @@ -496,7 +497,7 @@ public class LabeledPolynomialSpace>( } ) } - public operator fun Variable.minus(other: LabeledPolynomial): LabeledPolynomial = + public operator fun Symbol.minus(other: LabeledPolynomial): LabeledPolynomial = with(other.coefficients) { if (isEmpty()) LabeledPolynomial(mapOf(mapOf(this@minus to 1u) to constantOne)) else LabeledPolynomial( @@ -513,7 +514,7 @@ public class LabeledPolynomialSpace>( } ) } - public operator fun Variable.times(other: LabeledPolynomial): LabeledPolynomial = + public operator fun Symbol.times(other: LabeledPolynomial): LabeledPolynomial = LabeledPolynomial( other.coefficients .mapKeys { (degs, _) -> degs.toMutableMap().also{ it[this] = if (this in it) it[this]!! + 1U else 1U } } @@ -521,7 +522,7 @@ public class LabeledPolynomialSpace>( // endregion // region Polynomial-variable relation - public operator fun LabeledPolynomial.plus(other: Variable): LabeledPolynomial = + public operator fun LabeledPolynomial.plus(other: Symbol): LabeledPolynomial = with(coefficients) { if (isEmpty()) LabeledPolynomial(mapOf(mapOf(other to 1u) to constantOne)) else LabeledPolynomial( @@ -536,7 +537,7 @@ public class LabeledPolynomialSpace>( } ) } - public operator fun LabeledPolynomial.minus(other: Variable): LabeledPolynomial = + public operator fun LabeledPolynomial.minus(other: Symbol): LabeledPolynomial = with(coefficients) { if (isEmpty()) LabeledPolynomial(mapOf(mapOf(other to 1u) to constantOne)) else LabeledPolynomial( @@ -551,7 +552,7 @@ public class LabeledPolynomialSpace>( } ) } - public operator fun LabeledPolynomial.times(other: Variable): LabeledPolynomial = + public operator fun LabeledPolynomial.times(other: Symbol): LabeledPolynomial = LabeledPolynomial( coefficients .mapKeys { (degs, _) -> degs.toMutableMap().also{ it[other] = if (other in it) it[other]!! + 1U else 1U } } @@ -610,11 +611,11 @@ public class LabeledPolynomialSpace>( /** * Instance of zero polynomial (zero of the polynomial ring). */ - override val zero: LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to constantZero)) + override val zero: LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to constantZero)) /** * Instance of unit polynomial (unit of the polynomial ring). */ - override val one: LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to constantOne)) + override val one: LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to constantOne)) /** * Checks equality of the polynomials. @@ -642,7 +643,7 @@ public class LabeledPolynomialSpace>( * 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 LabeledPolynomial.degrees: Map + public val LabeledPolynomial.degrees: Map get() = buildMap { coefficients.entries.forEach { (degs, c) -> @@ -654,7 +655,7 @@ public class LabeledPolynomialSpace>( /** * Set of all variables that appear in the polynomial in positive exponents. */ - public val LabeledPolynomial.variables: Set + public val LabeledPolynomial.variables: Set get() = buildSet { coefficients.entries.forEach { (degs, c) -> if (c.isNotZero()) addAll(degs.keys) } @@ -695,29 +696,29 @@ public class LabeledPolynomialSpace>( } // @Suppress("NOTHING_TO_INLINE") -// public inline fun LabeledPolynomial.substitute(argument: Map): LabeledPolynomial = this.substitute(ring, argument) +// public inline fun LabeledPolynomial.substitute(argument: Map): LabeledPolynomial = this.substitute(ring, argument) // @Suppress("NOTHING_TO_INLINE") // @JvmName("substitutePolynomial") -// public inline fun LabeledPolynomial.substitute(argument: Map>): LabeledPolynomial = this.substitute(ring, argument) +// public inline fun LabeledPolynomial.substitute(argument: Map>): LabeledPolynomial = this.substitute(ring, argument) // // @Suppress("NOTHING_TO_INLINE") -// public inline fun LabeledPolynomial.asFunction(): (Map) -> LabeledPolynomial = { this.substitute(ring, it) } +// public inline fun LabeledPolynomial.asFunction(): (Map) -> LabeledPolynomial = { this.substitute(ring, it) } // @Suppress("NOTHING_TO_INLINE") -// public inline fun LabeledPolynomial.asFunctionOnConstants(): (Map) -> LabeledPolynomial = { this.substitute(ring, it) } +// public inline fun LabeledPolynomial.asFunctionOnConstants(): (Map) -> LabeledPolynomial = { this.substitute(ring, it) } // @Suppress("NOTHING_TO_INLINE") -// public inline fun LabeledPolynomial.asFunctionOnPolynomials(): (Map>) -> LabeledPolynomial = { this.substitute(ring, it) } +// public inline fun LabeledPolynomial.asFunctionOnPolynomials(): (Map>) -> LabeledPolynomial = { this.substitute(ring, it) } // // @Suppress("NOTHING_TO_INLINE") -// public inline operator fun LabeledPolynomial.invoke(argument: Map): LabeledPolynomial = this.substitute(ring, argument) +// public inline operator fun LabeledPolynomial.invoke(argument: Map): LabeledPolynomial = this.substitute(ring, argument) // @Suppress("NOTHING_TO_INLINE") // @JvmName("invokePolynomial") -// public inline operator fun LabeledPolynomial.invoke(argument: Map>): LabeledPolynomial = this.substitute(ring, argument) +// public inline operator fun LabeledPolynomial.invoke(argument: Map>): LabeledPolynomial = this.substitute(ring, argument) // endregion // region Utilities // TODO: Move to region internal utilities with context receiver @JvmName("applyAndRemoveZerosInternal") - internal fun MutableMap, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : MutableMap, C> { + internal fun MutableMap, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : MutableMap, C> { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } @@ -725,10 +726,10 @@ public class LabeledPolynomialSpace>( for ((degs, c) in this) if (c.isZero()) this.remove(degs) return this } - internal fun Map, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : Map, C> = + internal fun Map, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : Map, C> = toMutableMap().applyAndRemoveZeros(block) @OptIn(ExperimentalTypeInference::class) - internal inline fun buildCoefficients(@BuilderInference builderAction: MutableMap, C>.() -> Unit): Map, C> { + internal inline fun buildCoefficients(@BuilderInference builderAction: MutableMap, C>.() -> Unit): Map, C> { contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } return buildMap { builderAction() @@ -736,7 +737,7 @@ public class LabeledPolynomialSpace>( } } @OptIn(ExperimentalTypeInference::class) - internal inline fun buildCoefficients(capacity: Int, @BuilderInference builderAction: MutableMap, C>.() -> Unit): Map, C> { + internal inline fun buildCoefficients(capacity: Int, @BuilderInference builderAction: MutableMap, C>.() -> Unit): Map, C> { contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } return buildMap(capacity) { builderAction() diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt index df4441127..3077a2b82 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.functions +import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.invoke @@ -62,22 +63,22 @@ internal fun labeledRationalFunctionError(message: Any): Nothing = throw Labeled // ) // TODO: Rewrite former constructors as fabrics -//constructor(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>) : this( +//constructor(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>) : this( //LabeledPolynomial(numeratorCoefficients), //LabeledPolynomial(denominatorCoefficients) //) // -//constructor(numeratorCoefficients: Collection, C>>, denominatorCoefficients: Collection, C>>) : this( +//constructor(numeratorCoefficients: Collection, C>>, denominatorCoefficients: Collection, C>>) : this( //LabeledPolynomial(numeratorCoefficients), //LabeledPolynomial(denominatorCoefficients) //) // //constructor(numerator: LabeledPolynomial) : this(numerator, numerator.getOne()) -//constructor(numeratorCoefficients: Map, C>) : this( +//constructor(numeratorCoefficients: Map, C>) : this( //LabeledPolynomial(numeratorCoefficients) //) // -//constructor(numeratorCoefficients: Collection, C>>) : this( +//constructor(numeratorCoefficients: Collection, C>>) : this( //LabeledPolynomial(numeratorCoefficients) //) @@ -338,11 +339,11 @@ public class LabeledRationalFunctionSpace>( * 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 LabeledPolynomial.degrees: Map get() = polynomialRing { degrees } + public val LabeledPolynomial.degrees: Map get() = polynomialRing { degrees } /** * Set of all variables that appear in the polynomial in positive exponents. */ - public val LabeledPolynomial.variables: Set get() = polynomialRing { variables } + public val LabeledPolynomial.variables: Set get() = polynomialRing { variables } /** * Count of all variables that appear in the polynomial in positive exponents. */ @@ -353,7 +354,7 @@ public class LabeledRationalFunctionSpace>( /** * Count of all variables that appear in the polynomial in positive exponents. */ - public val LabeledRationalFunction.variables: Set + public val LabeledRationalFunction.variables: Set get() = numerator.variables union denominator.variables /** * Count of all variables that appear in the polynomial in positive exponents. @@ -381,21 +382,21 @@ public class LabeledRationalFunctionSpace>( denominator * other ) -// operator fun invoke(arg: Map): LabeledRationalFunction = +// operator fun invoke(arg: Map): LabeledRationalFunction = // LabeledRationalFunction( // numerator(arg), // denominator(arg) // ) // // @JvmName("invokeLabeledPolynomial") -// operator fun invoke(arg: Map>): LabeledRationalFunction = +// operator fun invoke(arg: Map>): LabeledRationalFunction = // LabeledRationalFunction( // numerator(arg), // denominator(arg) // ) // // @JvmName("invokeLabeledRationalFunction") -// operator fun invoke(arg: Map>): LabeledRationalFunction { +// operator fun invoke(arg: Map>): LabeledRationalFunction { // var num = numerator invokeRFTakeNumerator arg // var den = denominator invokeRFTakeNumerator arg // for (variable in variables) if (variable in arg) { @@ -410,56 +411,56 @@ public class LabeledRationalFunctionSpace>( // // override fun toString(): String = toString(emptyMap()) // -// fun toString(names: Map = emptyMap()): String = +// fun toString(names: Map = emptyMap()): String = // when (true) { // numerator.isZero() -> "0" // denominator.isOne() -> numerator.toString(names) // else -> "${numerator.toStringWithBrackets(names)}/${denominator.toStringWithBrackets(names)}" // } // -// fun toString(namer: (Variable) -> String): String = +// fun toString(namer: (Symbol) -> String): String = // when (true) { // numerator.isZero() -> "0" // denominator.isOne() -> numerator.toString(namer) // else -> "${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)}" // } // -// fun toStringWithBrackets(names: Map = emptyMap()): String = +// fun toStringWithBrackets(names: Map = emptyMap()): String = // when (true) { // numerator.isZero() -> "0" // denominator.isOne() -> numerator.toStringWithBrackets(names) // else -> "(${numerator.toStringWithBrackets(names)}/${denominator.toStringWithBrackets(names)})" // } // -// fun toStringWithBrackets(namer: (Variable) -> String): String = +// fun toStringWithBrackets(namer: (Symbol) -> String): String = // when (true) { // numerator.isZero() -> "0" // denominator.isOne() -> numerator.toStringWithBrackets(namer) // else -> "(${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)})" // } // -// fun toReversedString(names: Map = emptyMap()): String = +// fun toReversedString(names: Map = emptyMap()): String = // when (true) { // numerator.isZero() -> "0" // denominator.isOne() -> numerator.toReversedString(names) // else -> "${numerator.toReversedStringWithBrackets(names)}/${denominator.toReversedStringWithBrackets(names)}" // } // -// fun toReversedString(namer: (Variable) -> String): String = +// fun toReversedString(namer: (Symbol) -> String): String = // when (true) { // numerator.isZero() -> "0" // denominator.isOne() -> numerator.toReversedString(namer) // else -> "${numerator.toReversedStringWithBrackets(namer)}/${denominator.toReversedStringWithBrackets(namer)}" // } // -// fun toReversedStringWithBrackets(names: Map = emptyMap()): String = +// fun toReversedStringWithBrackets(names: Map = emptyMap()): String = // when (true) { // numerator.isZero() -> "0" // denominator.isOne() -> numerator.toReversedStringWithBrackets(names) // else -> "(${numerator.toReversedStringWithBrackets(names)}/${denominator.toReversedStringWithBrackets(names)})" // } // -// fun toReversedStringWithBrackets(namer: (Variable) -> String): String = +// fun toReversedStringWithBrackets(namer: (Symbol) -> String): String = // when (true) { // numerator.isZero() -> "0" // denominator.isOne() -> numerator.toReversedStringWithBrackets(namer) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Variable.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Variable.kt deleted file mode 100644 index 410604fd3..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Variable.kt +++ /dev/null @@ -1,38 +0,0 @@ -package space.kscience.kmath.functions - -import kotlin.reflect.KProperty - - -/** - * Represents class of labeled variables like usual - * `x`, `y`, `z`, `a`, `b`, `n`, `m`, etc. - * - * Variables does not contain any information about field (or ring, ets.) they are considered in - * and therefore about coefficient. - * - * @property name Is the label or name of variable. For `x` it is `"x"`, for `n` – `"n"`, etc. - */ -public data class Variable (val name: String) : Comparable { - /** - * Represents the variable as a string. - * - * @return Only name of the variable. - */ - override fun toString(): String = name - /** - * Compares two variables. - * Comparison is realised by comparison of variables' names. - * - * Used in [LabeledPolynomial] and [LabeledRationalFunction] to sort monomials in - * [LabeledPolynomial.toString] and [LabeledRationalFunction.toString] in lexicographic order. - * - * @see Comparable.compareTo - * @sample LabeledPolynomial.monomialComparator - * @return Only name of the variable. - */ - override fun compareTo(other: Variable): Int = name.compareTo(other.name) - - public companion object { - public operator fun getValue(thisRef: Any?, property: KProperty<*>) : Variable = Variable(property.name) - } -} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt index 544cca410..9408a09f2 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt @@ -5,10 +5,14 @@ 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.* -import kotlin.math.max +import space.kscience.kmath.operations.Field +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.invoke +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract // TODO: Docs @@ -31,10 +35,10 @@ import kotlin.math.max // //// endregion -//// region Variables +//// region Symbols // //context(LabeledPolynomialSpace) -//fun > power(arg: Variable, pow: UInt): LabeledPolynomial = +//fun > power(arg: Symbol, pow: UInt): LabeledPolynomial = // if (pow == 0U) one // else LabeledPolynomial(mapOf( // mapOf(arg to pow) to constantOne @@ -45,7 +49,7 @@ import kotlin.math.max //// region Polynomials // //context(LabeledPolynomialSpace) -//fun > number(value: Int): LabeledPolynomial = ring { LabeledPolynomial(mapOf(emptyMap() to number(value))) } +//fun > number(value: Int): LabeledPolynomial = ring { LabeledPolynomial(mapOf(emptyMap() to number(value))) } // //context(LabeledPolynomialSpace) //fun > multiplyWithPower(base: LabeledPolynomial, arg: LabeledPolynomial, pow: UInt): LabeledPolynomial = @@ -97,7 +101,7 @@ public inline fun , R> A.labeledPolynomial(block: LabeledPolynomi // * Consider that monomials are sorted in lexicographic order. // */ //context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.represent(names: Map = emptyMap()): String = +//fun > LabeledPolynomial.represent(names: Map = emptyMap()): String = // coefficients.entries // .sortedWith { o1, o2 -> LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } // .asSequence() @@ -130,7 +134,7 @@ public inline fun , R> A.labeledPolynomial(block: LabeledPolynomi // * Consider that monomials are sorted in lexicographic order. // */ //context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.represent(namer: (Variable) -> String): String = +//fun > LabeledPolynomial.represent(namer: (Symbol) -> String): String = // coefficients.entries // .sortedWith { o1, o2 -> LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } // .asSequence() @@ -163,7 +167,7 @@ public inline fun , R> A.labeledPolynomial(block: LabeledPolynomi // * Consider that monomials are sorted in lexicographic order. // */ //context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.representWithBrackets(names: Map = emptyMap()): String = +//fun > LabeledPolynomial.representWithBrackets(names: Map = emptyMap()): String = // with(represent(names)) { if (coefficients.count() == 1) this else "($this)" } // ///** @@ -172,7 +176,7 @@ public inline fun , R> A.labeledPolynomial(block: LabeledPolynomi // * Consider that monomials are sorted in lexicographic order. // */ //context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.representWithBrackets(namer: (Variable) -> String): String = +//fun > LabeledPolynomial.representWithBrackets(namer: (Symbol) -> String): String = // with(represent(namer)) { if (coefficients.count() == 1) this else "($this)" } // ///** @@ -180,7 +184,7 @@ public inline fun , R> A.labeledPolynomial(block: LabeledPolynomi // * Consider that monomials are sorted in **reversed** lexicographic order. // */ //context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.representReversed(names: Map = emptyMap()): String = +//fun > LabeledPolynomial.representReversed(names: Map = emptyMap()): String = // coefficients.entries // .sortedWith { o1, o2 -> -LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } // .asSequence() @@ -213,7 +217,7 @@ public inline fun , R> A.labeledPolynomial(block: LabeledPolynomi // * Consider that monomials are sorted in **reversed** lexicographic order. // */ //context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.representReversed(namer: (Variable) -> String): String = +//fun > LabeledPolynomial.representReversed(namer: (Symbol) -> String): String = // coefficients.entries // .sortedWith { o1, o2 -> -LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } // .asSequence() @@ -246,7 +250,7 @@ public inline fun , R> A.labeledPolynomial(block: LabeledPolynomi // * Consider that monomials are sorted in **reversed** lexicographic order. // */ //context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.representReversedWithBrackets(names: Map = emptyMap()): String = +//fun > LabeledPolynomial.representReversedWithBrackets(names: Map = emptyMap()): String = // with(representReversed(names)) { if (coefficients.count() == 1) this else "($this)" } // ///** @@ -255,7 +259,7 @@ public inline fun , R> A.labeledPolynomial(block: LabeledPolynomi // * Consider that monomials are sorted in **reversed** lexicographic order. // */ //context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.representReversedWithBrackets(namer: (Variable) -> String): String = +//fun > LabeledPolynomial.representReversedWithBrackets(namer: (Symbol) -> String): String = // with(representReversed(namer)) { if (coefficients.count() == 1) this else "($this)" } // //// endregion @@ -279,7 +283,7 @@ public inline fun , R> A.labeledPolynomial(block: LabeledPolynomi //// region Polynomial substitution and functional representation // -//public fun LabeledPolynomial.substitute(ring: Ring, args: Map): LabeledPolynomial = ring { +//public fun LabeledPolynomial.substitute(ring: Ring, args: Map): LabeledPolynomial = ring { // if (coefficients.isEmpty()) return this@substitute // LabeledPolynomial( // buildMap { @@ -297,7 +301,7 @@ public inline fun , R> A.labeledPolynomial(block: LabeledPolynomi //// TODO: Replace with optimisation: the [result] may be unboxed, and all operations may be performed as soon as //// possible on it //@JvmName("substitutePolynomial") -//fun LabeledPolynomial.substitute(ring: Ring, arg: Map>) : LabeledPolynomial = +//fun LabeledPolynomial.substitute(ring: Ring, arg: Map>) : LabeledPolynomial = // ring.labeledPolynomial { // if (coefficients.isEmpty()) return zero // coefficients @@ -315,10 +319,10 @@ public inline fun , R> A.labeledPolynomial(block: LabeledPolynomi // //// TODO: Substitute rational function // -//fun > LabeledPolynomial.asFunctionOver(ring: A): (Map) -> LabeledPolynomial = +//fun > LabeledPolynomial.asFunctionOver(ring: A): (Map) -> LabeledPolynomial = // { substitute(ring, it) } // -//fun > LabeledPolynomial.asPolynomialFunctionOver(ring: A): (Map>) -> LabeledPolynomial = +//fun > LabeledPolynomial.asPolynomialFunctionOver(ring: A): (Map>) -> LabeledPolynomial = // { substitute(ring, it) } // //// endregion @@ -331,7 +335,7 @@ public inline fun , R> A.labeledPolynomial(block: LabeledPolynomi @UnstableKMathAPI public fun > LabeledPolynomial.derivativeWithRespectTo( algebra: A, - variable: Variable, + variable: Symbol, ): LabeledPolynomial = algebra { LabeledPolynomial( buildMap(coefficients.size) { @@ -360,7 +364,7 @@ public fun > LabeledPolynomial.derivativeWithRespectTo( @UnstableKMathAPI public fun > LabeledPolynomial.derivativeWithRespectTo( algebra: A, - variables: Collection, + variables: Collection, ): LabeledPolynomial = algebra { val cleanedVariables = variables.toSet() if (cleanedVariables.isEmpty()) return this@derivativeWithRespectTo @@ -391,7 +395,7 @@ public fun > LabeledPolynomial.derivativeWithRespectTo( @UnstableKMathAPI public fun > LabeledPolynomial.nthDerivativeWithRespectTo( algebra: A, - variable: Variable, + variable: Symbol, order: UInt ): LabeledPolynomial = algebra { if (order == 0u) return this@nthDerivativeWithRespectTo @@ -425,7 +429,7 @@ public fun > LabeledPolynomial.nthDerivativeWithRespectTo( @UnstableKMathAPI public fun > LabeledPolynomial.nthDerivativeWithRespectTo( algebra: A, - variablesAndOrders: Map, + variablesAndOrders: Map, ): LabeledPolynomial = algebra { val filteredVariablesAndOrders = variablesAndOrders.filterValues { it != 0u } if (filteredVariablesAndOrders.isEmpty()) return this@nthDerivativeWithRespectTo @@ -462,13 +466,13 @@ public fun > LabeledPolynomial.nthDerivativeWithRespectTo( @UnstableKMathAPI public fun > LabeledPolynomial.antiderivativeWithRespectTo( algebra: A, - variable: Variable, + variable: Symbol, ): LabeledPolynomial = algebra { LabeledPolynomial( buildMap(coefficients.size) { coefficients .forEach { (degs, c) -> - val newDegs = buildMap(degs.size + 1) { + val newDegs = buildMap(degs.size + 1) { put(variable, 1u) for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) } @@ -487,7 +491,7 @@ public fun > LabeledPolynomial.antiderivativeWithRespectTo( @UnstableKMathAPI public fun > LabeledPolynomial.antiderivativeWithRespectTo( algebra: A, - variables: Collection, + variables: Collection, ): LabeledPolynomial = algebra { val cleanedVariables = variables.toSet() if (cleanedVariables.isEmpty()) return this@antiderivativeWithRespectTo @@ -495,7 +499,7 @@ public fun > LabeledPolynomial.antiderivativeWithRespectTo( buildMap(coefficients.size) { coefficients .forEach { (degs, c) -> - val newDegs = buildMap(degs.size + 1) { + val newDegs = buildMap(degs.size + 1) { for (variable in cleanedVariables) put(variable, 1u) for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) } @@ -514,7 +518,7 @@ public fun > LabeledPolynomial.antiderivativeWithRespectTo( @UnstableKMathAPI public fun > LabeledPolynomial.nthAntiderivativeWithRespectTo( algebra: A, - variable: Variable, + variable: Symbol, order: UInt ): LabeledPolynomial = algebra { if (order == 0u) return this@nthAntiderivativeWithRespectTo @@ -522,7 +526,7 @@ public fun > LabeledPolynomial.nthAntiderivativeWithRespectTo buildMap(coefficients.size) { coefficients .forEach { (degs, c) -> - val newDegs = buildMap(degs.size + 1) { + val newDegs = buildMap(degs.size + 1) { put(variable, order) for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) } @@ -544,7 +548,7 @@ public fun > LabeledPolynomial.nthAntiderivativeWithRespectTo @UnstableKMathAPI public fun > LabeledPolynomial.nthAntiderivativeWithRespectTo( algebra: A, - variablesAndOrders: Map, + variablesAndOrders: Map, ): LabeledPolynomial = algebra { val filteredVariablesAndOrders = variablesAndOrders.filterValues { it != 0u } if (filteredVariablesAndOrders.isEmpty()) return this@nthAntiderivativeWithRespectTo @@ -552,7 +556,7 @@ public fun > LabeledPolynomial.nthAntiderivativeWithRespectTo buildMap(coefficients.size) { coefficients .forEach { (degs, c) -> - val newDegs = buildMap(degs.size + 1) { + val newDegs = buildMap(degs.size + 1) { for ((variable, order) in filteredVariablesAndOrders) put(variable, order) for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) } -- 2.34.1 From 24944cdb1639bc6bec924510686052e979bb4561 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Wed, 16 Mar 2022 15:19:27 +0300 Subject: [PATCH 033/275] Added support of `power` function to abstract structures. Implemented exponentiation by squaring as default implementation of `power`. Updated docs in algebraicStub.kt and updated realisations in it. --- .../kmath/functions/AbstractPolynomial.kt | 39 ++++-- .../functions/AbstractRationalFunction.kt | 52 ++++++-- .../kscience/kmath/functions/algebraicStub.kt | 124 ++++++++++++++---- .../kmath/functions/labeledPolynomialUtil.kt | 16 +-- .../kmath/functions/numberedPolynomialUtil.kt | 16 +-- .../kmath/functions/polynomialUtil.kt | 2 +- 6 files changed, 181 insertions(+), 68 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt index 8bd8697e3..2d2d22fd3 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt @@ -71,19 +71,19 @@ public interface AbstractPolynomialSpace> : Ring

* * The operation is equivalent to adding [other] copies of unit polynomial to [this]. */ - public operator fun P.plus(other: Int): P = optimizedAddMultiplied(this, one, other) + public operator fun P.plus(other: Int): P = addMultipliedBySquaring(this, one, other) /** * Returns difference between the polynomial and the integer represented as polynomial. * * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. */ - public operator fun P.minus(other: Int): P = optimizedAddMultiplied(this, one, -other) + public operator fun P.minus(other: Int): P = addMultipliedBySquaring(this, one, -other) /** * Returns product of the polynomial and the integer represented as polynomial. * * The operation is equivalent to sum of [other] copies of [this]. */ - public operator fun P.times(other: Int): P = optimizedMultiply(this, other) + public operator fun P.times(other: Int): P = multiplyBySquaring(this, other) // endregion // region Integer-polynomial relation @@ -92,19 +92,19 @@ public interface AbstractPolynomialSpace> : Ring

* * The operation is equivalent to adding [this] copies of unit polynomial to [other]. */ - public operator fun Int.plus(other: P): P = optimizedAddMultiplied(other, one, this) + public operator fun Int.plus(other: P): P = addMultipliedBySquaring(other, one, this) /** * Returns difference between the integer represented as 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 = optimizedAddMultiplied(-other, one, this) + public operator fun Int.minus(other: P): P = addMultipliedBySquaring(-other, one, this) /** * Returns product of the integer represented as polynomial and the polynomial. * * The operation is equivalent to sum of [this] copies of [other]. */ - public operator fun Int.times(other: P): P = optimizedMultiply(other, this) + public operator fun Int.times(other: P): P = multiplyBySquaring(other, this) // endregion // region Constant-constant relation @@ -138,6 +138,12 @@ public interface AbstractPolynomialSpace> : Ring

@JvmName("constantTimes") @JsName("constantTimes") public operator fun C.times(other: C): C + /** + * Raises [arg] to the integer power [exponent]. + */ + @JvmName("constantPower") + @JsName("constantPower") + public fun power(arg: C, exponent: UInt) : C /** * Check if the instant is zero constant. @@ -225,6 +231,10 @@ public interface AbstractPolynomialSpace> : Ring

* 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 = exponentiationBySquaring(arg, exponent) /** * Check if the instant is zero polynomial. @@ -331,19 +341,19 @@ public interface AbstractPolynomialSpaceOverRing, A: * * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. */ - public override operator fun C.plus(other: Int): C = ring { optimizedAddMultiplied(this@plus, one, other) } + public override operator fun C.plus(other: Int): C = ring { addMultipliedBySquaring(this@plus, one, other) } /** * Returns difference between the constant and the integer represented as constant (member of underlying ring). * * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. */ - public override operator fun C.minus(other: Int): C = ring { optimizedAddMultiplied(this@minus, one, -other) } + public override operator fun C.minus(other: Int): C = ring { addMultipliedBySquaring(this@minus, one, -other) } /** * Returns product of the constant and the integer represented as constant (member of underlying ring). * * The operation is equivalent to sum of [other] copies of [this]. */ - public override operator fun C.times(other: Int): C = ring { optimizedMultiply(this@times, other) } + public override operator fun C.times(other: Int): C = ring { multiplyBySquaring(this@times, other) } // endregion // region Integer-constant relation @@ -352,19 +362,19 @@ public interface AbstractPolynomialSpaceOverRing, A: * * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. */ - public override operator fun Int.plus(other: C): C = ring { optimizedAddMultiplied(other, one, this@plus) } + public override operator fun Int.plus(other: C): C = ring { addMultipliedBySquaring(other, one, this@plus) } /** * Returns difference between the integer represented as constant (member of underlying ring) and the constant. * * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. */ - public override operator fun Int.minus(other: C): C = ring { optimizedAddMultiplied(-other, one, this@minus) } + public override operator fun Int.minus(other: C): C = ring { addMultipliedBySquaring(-other, one, this@minus) } /** * Returns product of the integer represented as constant (member of underlying ring) and the constant. * * The operation is equivalent to sum of [this] copies of [other]. */ - public override operator fun Int.times(other: C): C = ring { optimizedMultiply(other, this@times) } + public override operator fun Int.times(other: C): C = ring { multiplyBySquaring(other, this@times) } // endregion // region Constant-constant relation @@ -388,6 +398,11 @@ public interface AbstractPolynomialSpaceOverRing, A: */ @JvmName("constantTimes") public override operator fun C.times(other: C): C = ring { this@times * other } + /** + * Raises [arg] to the integer power [exponent]. + */ + @JvmName("constantPower") + override fun power(arg: C, exponent: UInt): C = ring { power(arg, exponent) } /** * Instance of zero constant (zero of the underlying ring). diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt index 685cf4ca3..c6f1d7a7a 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt @@ -120,19 +120,19 @@ public interface AbstractRationalFunctionalSpace, R: * * The operation is equivalent to adding [other] copies of unit polynomial to [this]. */ - public operator fun R.plus(other: Int): R = optimizedAddMultiplied(this, one, other) + public operator fun R.plus(other: Int): R = addMultipliedBySquaring(this, one, other) /** * Returns difference between the rational function and the integer represented as rational function. * * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. */ - public operator fun R.minus(other: Int): R = optimizedAddMultiplied(this, one, -other) + public operator fun R.minus(other: Int): R = addMultipliedBySquaring(this, one, -other) /** * Returns product of the rational function and the integer represented as rational function. * * The operation is equivalent to sum of [other] copies of [this]. */ - public operator fun R.times(other: Int): R = optimizedMultiply(this, other) + public operator fun R.times(other: Int): R = multiplyBySquaring(this, other) // endregion // region Integer-Rational relation @@ -141,19 +141,19 @@ public interface AbstractRationalFunctionalSpace, R: * * The operation is equivalent to adding [this] copies of unit polynomial to [other]. */ - public operator fun Int.plus(other: R): R = optimizedAddMultiplied(other, one, this) + public operator fun Int.plus(other: R): R = addMultipliedBySquaring(other, one, this) /** * Returns difference between the integer represented as 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 = optimizedAddMultiplied(-other, one, this) + public operator fun Int.minus(other: R): R = addMultipliedBySquaring(-other, one, this) /** * Returns product of the integer represented as 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 = optimizedMultiply(other, this) + public operator fun Int.times(other: R): R = multiplyBySquaring(other, this) // endregion // region Constant-constant relation @@ -187,6 +187,12 @@ public interface AbstractRationalFunctionalSpace, R: @JvmName("constantTimes") @JsName("constantTimes") public operator fun C.times(other: C): C + /** + * Raises [arg] to the integer power [exponent]. + */ + @JvmName("constantPower") + @JsName("constantPower") + public fun power(arg: C, exponent: UInt) : C /** * Check if the instant is zero constant. @@ -274,6 +280,10 @@ public interface AbstractRationalFunctionalSpace, R: * Returns product of the polynomials. */ public operator fun P.times(other: P): P + /** + * Raises [arg] to the integer power [exponent]. + */ + public fun power(arg: P, exponent: UInt) : P /** * Check if the instant is zero polynomial. @@ -400,6 +410,10 @@ public interface AbstractRationalFunctionalSpace, R: * Returns product of the rational functions. */ public override operator fun R.times(other: R): R + /** + * Raises [arg] to the integer power [exponent]. + */ + public override fun power(arg: R, exponent: UInt) : R = exponentiationBySquaring(arg, exponent) /** * Check if the instant is zero rational function. @@ -536,19 +550,19 @@ public interface AbstractRationalFunctionalSpaceOverRing Group.optimizedMultiply(arg: C, other: Int): C = - if (other >= 0) optimizedMultiply(arg, other.toUInt()) - else optimizedMultiply(arg, (-other).toUInt()) +internal fun Group.multiplyBySquaring(arg: C, multiplier: Int): C = + if (multiplier >= 0) multiplyBySquaring(arg, multiplier.toUInt()) + else multiplyBySquaring(-arg, (-multiplier).toUInt()) // TODO: Move receiver to context receiver /** * Adds product of [arg] and [multiplier] to [base]. * - * @receiver the algebra to provide multiplication. * @param base the augend. * @param arg the multiplicand. - * @param multiplier the multiplier. + * @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 Group.optimizedAddMultiplied(base: C, arg: C, multiplier: Int): C = - if (multiplier >= 0) optimizedAddMultiplied(base, arg, multiplier.toUInt()) - else optimizedAddMultiplied(base, arg, (-multiplier).toUInt()) +internal fun GroupOps.addMultipliedBySquaring(base: C, arg: C, multiplier: Int): C = + if (multiplier >= 0) addMultipliedBySquaring(base, arg, multiplier.toUInt()) + else addMultipliedBySquaring(base, -arg, (-multiplier).toUInt()) // TODO: Move receiver to context receiver /** - * Multiplication of element and integer. + * Returns product of [arg] and integer [multiplier]. * - * @receiver the multiplicand. - * @param other the multiplier. - * @return the difference. + * 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.optimizedMultiply(arg: C, other: UInt): C = +internal tailrec fun Group.multiplyBySquaring(arg: C, multiplier: UInt): C = when { - other == 0u -> zero - other == 1u -> arg - other % 2u == 0u -> optimizedMultiply(arg + arg, other / 2u) - other % 2u == 1u -> optimizedAddMultiplied(arg, arg + arg, other / 2u) + multiplier == 0u -> zero + multiplier == 1u -> arg + multiplier and 1u == 0u -> multiplyBySquaring(arg + arg, multiplier shr 1) + multiplier and 1u == 1u -> addMultipliedBySquaring(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") } @@ -59,18 +60,87 @@ internal tailrec fun Group.optimizedMultiply(arg: C, other: UInt): C = /** * Adds product of [arg] and [multiplier] to [base]. * - * @receiver the algebra to provide multiplication. + * 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 multiplier. + * @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 Group.optimizedAddMultiplied(base: C, arg: C, multiplier: UInt): C = +internal tailrec fun GroupOps.addMultipliedBySquaring(base: C, arg: C, multiplier: UInt): C = when { multiplier == 0u -> base multiplier == 1u -> base + arg - multiplier % 2u == 0u -> optimizedAddMultiplied(base, arg + arg, multiplier / 2u) - multiplier % 2u == 1u -> optimizedAddMultiplied(base + arg, arg + arg, multiplier / 2u) + multiplier and 1u == 0u -> addMultipliedBySquaring(base, arg + arg, multiplier shr 1) + multiplier and 1u == 1u -> addMultipliedBySquaring(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") + } + +// TODO: 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.exponentiationBySquaring(arg: C, exponent: Int): C = + if (exponent >= 0) exponentiationBySquaring(arg, exponent.toUInt()) + else exponentiationBySquaring(one / arg, (-exponent).toUInt()) + +// TODO: 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.multiplyExponentiationBySquaring(base: C, arg: C, exponent: Int): C = + if (exponent >= 0) multiplyExponentiationBySquaring(base, arg, exponent.toUInt()) + else multiplyExponentiationBySquaring(base, one / arg, (-exponent).toUInt()) + +// TODO: 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.exponentiationBySquaring(arg: C, exponent: UInt): C = + when { + exponent == 0u -> zero + exponent == 1u -> arg + exponent and 1u == 0u -> exponentiationBySquaring(arg * arg, exponent shr 1) + exponent and 1u == 1u -> multiplyExponentiationBySquaring(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") + } + +// TODO: 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.multiplyExponentiationBySquaring(base: C, arg: C, exponent: UInt): C = + when { + exponent == 0u -> base + exponent == 1u -> base + arg + exponent and 1u == 0u -> multiplyExponentiationBySquaring(base, arg * arg, exponent shr 1) + exponent and 1u == 1u -> multiplyExponentiationBySquaring(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-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt index 9408a09f2..516e76b8f 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt @@ -351,7 +351,7 @@ public fun > LabeledPolynomial.derivativeWithRespectTo( } } }, - optimizedMultiply(c, degs[variable]!!) + multiplyBySquaring(c, degs[variable]!!) ) } } @@ -382,7 +382,7 @@ public fun > LabeledPolynomial.derivativeWithRespectTo( } } }, - cleanedVariables.fold(c) { acc, variable -> optimizedMultiply(acc, degs[variable]!!) } + cleanedVariables.fold(c) { acc, variable -> multiplyBySquaring(acc, degs[variable]!!) } ) } } @@ -415,7 +415,7 @@ public fun > LabeledPolynomial.nthDerivativeWithRespectTo( }, degs[variable]!!.let { deg -> (deg downTo deg - order + 1u) - .fold(c) { acc, ord -> optimizedMultiply(acc, ord) } + .fold(c) { acc, ord -> multiplyBySquaring(acc, ord) } } ) } @@ -451,7 +451,7 @@ public fun > LabeledPolynomial.nthDerivativeWithRespectTo( filteredVariablesAndOrders.entries.fold(c) { acc1, (index, order) -> degs[index]!!.let { deg -> (deg downTo deg - order + 1u) - .fold(acc1) { acc2, ord -> optimizedMultiply(acc2, ord) } + .fold(acc1) { acc2, ord -> multiplyBySquaring(acc2, ord) } } } ) @@ -478,7 +478,7 @@ public fun > LabeledPolynomial.antiderivativeWithRespectTo( } put( newDegs, - c / optimizedMultiply(one, newDegs[variable]!!) + c / multiplyBySquaring(one, newDegs[variable]!!) ) } } @@ -505,7 +505,7 @@ public fun > LabeledPolynomial.antiderivativeWithRespectTo( } put( newDegs, - cleanedVariables.fold(c) { acc, variable -> acc / optimizedMultiply(one, newDegs[variable]!!) } + cleanedVariables.fold(c) { acc, variable -> acc / multiplyBySquaring(one, newDegs[variable]!!) } ) } } @@ -534,7 +534,7 @@ public fun > LabeledPolynomial.nthAntiderivativeWithRespectTo newDegs, newDegs[variable]!!.let { deg -> (deg downTo deg - order + 1u) - .fold(c) { acc, ord -> acc / optimizedMultiply(one, ord) } + .fold(c) { acc, ord -> acc / multiplyBySquaring(one, ord) } } ) } @@ -565,7 +565,7 @@ public fun > LabeledPolynomial.nthAntiderivativeWithRespectTo filteredVariablesAndOrders.entries.fold(c) { acc1, (index, order) -> newDegs[index]!!.let { deg -> (deg downTo deg - order + 1u) - .fold(acc1) { acc2, ord -> acc2 / optimizedMultiply(one, ord) } + .fold(acc1) { acc2, ord -> acc2 / multiplyBySquaring(one, ord) } } } ) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt index 47644b26a..ac411fc28 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt @@ -393,7 +393,7 @@ public fun > NumberedPolynomial.derivativeWithRespectTo( else -> return@forEach } }.cleanUp(), - optimizedMultiply(c, degs[variable]) + multiplyBySquaring(c, degs[variable]) ) } } @@ -424,7 +424,7 @@ public fun > NumberedPolynomial.derivativeWithRespectTo( else -> return@forEach } }.cleanUp(), - cleanedVariables.fold(c) { acc, variable -> optimizedMultiply(acc, degs[variable]) } + cleanedVariables.fold(c) { acc, variable -> multiplyBySquaring(acc, degs[variable]) } ) } } @@ -456,7 +456,7 @@ public fun > NumberedPolynomial.nthDerivativeWithRespectTo( }.cleanUp(), degs[variable].let { deg -> (deg downTo deg - order + 1u) - .fold(c) { acc, ord -> optimizedMultiply(acc, ord) } + .fold(c) { acc, ord -> multiplyBySquaring(acc, ord) } } ) } @@ -489,7 +489,7 @@ public fun > NumberedPolynomial.nthDerivativeWithRespectTo( filteredVariablesAndOrders.entries.fold(c) { acc1, (index, order) -> degs[index].let { deg -> (deg downTo deg - order + 1u) - .fold(acc1) { acc2, ord -> optimizedMultiply(acc2, ord) } + .fold(acc1) { acc2, ord -> multiplyBySquaring(acc2, ord) } } } ) @@ -512,7 +512,7 @@ public fun > NumberedPolynomial.antiderivativeWithRespectTo( .forEach { (degs, c) -> put( List(max(variable + 1, degs.size)) { if (it != variable) degs[it] else degs[it] + 1u }, - c / optimizedMultiply(one, degs[variable]) + c / multiplyBySquaring(one, degs[variable]) ) } } @@ -536,7 +536,7 @@ public fun > NumberedPolynomial.antiderivativeWithRespectTo( .forEach { (degs, c) -> put( List(max(maxRespectedVariable + 1, degs.size)) { if (it !in variables) degs[it] else degs[it] + 1u }, - cleanedVariables.fold(c) { acc, variable -> acc / optimizedMultiply(one, degs[variable]) } + cleanedVariables.fold(c) { acc, variable -> acc / multiplyBySquaring(one, degs[variable]) } ) } } @@ -561,7 +561,7 @@ public fun > NumberedPolynomial.nthAntiderivativeWithRespectT List(max(variable + 1, degs.size)) { if (it != variable) degs[it] else degs[it] + order }, degs[variable].let { deg -> (deg downTo deg - order + 1u) - .fold(c) { acc, ord -> acc / optimizedMultiply(one, ord) } + .fold(c) { acc, ord -> acc / multiplyBySquaring(one, ord) } } ) } @@ -589,7 +589,7 @@ public fun > NumberedPolynomial.nthAntiderivativeWithRespectT filteredVariablesAndOrders.entries.fold(c) { acc1, (index, order) -> degs[index].let { deg -> (deg downTo deg - order + 1u) - .fold(acc1) { acc2, ord -> acc2 / optimizedMultiply(one, ord) } + .fold(acc1) { acc2, ord -> acc2 / multiplyBySquaring(one, ord) } } } ) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt index 9c8cc0090..2d0377d2c 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt @@ -137,7 +137,7 @@ public fun Polynomial.derivative( public fun Polynomial.nthDerivative( algebra: A, order: UInt, -): Polynomial where A : Ring, A : NumericAlgebra = algebra { +): Polynomial where A : Ring, A : NumericAlgebra = algebra { Polynomial(coefficients.drop(order.toInt()).mapIndexed { index, c -> (index + 1..index + order.toInt()).fold(c) { acc, i -> acc * number(i) } }) } -- 2.34.1 From 3c9d8a4eee586962ba59a3790c3d7ddb18572637 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Wed, 16 Mar 2022 22:44:55 +0300 Subject: [PATCH 034/275] Deleted all region marks --- .../kmath/functions/AbstractPolynomial.kt | 27 ------- .../functions/AbstractRationalFunction.kt | 79 ------------------- .../kmath/functions/LabeledPolynomial.kt | 40 +--------- .../functions/LabeledRationalFunction.kt | 27 +------ .../kmath/functions/NumberedPolynomial.kt | 29 +------ .../functions/NumberedRationalFunction.kt | 27 +------ .../kscience/kmath/functions/Polynomial.kt | 1 - .../kmath/functions/RationalFunction.kt | 24 +----- .../kmath/functions/labeledPolynomialUtil.kt | 37 +-------- .../functions/labeledRationalFunctionUtil.kt | 10 +-- .../kmath/functions/numberedPolynomialUtil.kt | 42 +--------- .../functions/numberedRationalFunctionUtil.kt | 10 +-- .../kmath/functions/polynomialUtil.kt | 14 +--- .../kmath/functions/rationalFunctionUtil.kt | 12 +-- 14 files changed, 11 insertions(+), 368 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt index 2d2d22fd3..aacf055fa 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt @@ -23,7 +23,6 @@ public interface AbstractPolynomial */ @Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") public interface AbstractPolynomialSpace> : Ring

{ - // region Constant-integer relation /** * Returns sum of the constant and the integer represented as constant (member of underlying ring). * @@ -42,9 +41,7 @@ public interface AbstractPolynomialSpace> : Ring

* The operation is equivalent to sum of [other] copies of [this]. */ public operator fun C.times(other: Int): C - // endregion - // region Integer-constant relation /** * Returns sum of the integer represented as constant (member of underlying ring) and the constant. * @@ -63,9 +60,7 @@ public interface AbstractPolynomialSpace> : Ring

* The operation is equivalent to sum of [this] copies of [other]. */ public operator fun Int.times(other: C): C - // endregion - // region Polynomial-integer relation /** * Returns sum of the polynomial and the integer represented as polynomial. * @@ -84,9 +79,7 @@ public interface AbstractPolynomialSpace> : Ring

* The operation is equivalent to sum of [other] copies of [this]. */ public operator fun P.times(other: Int): P = multiplyBySquaring(this, other) - // endregion - // region Integer-polynomial relation /** * Returns sum of the integer represented as polynomial and the polynomial. * @@ -105,9 +98,7 @@ public interface AbstractPolynomialSpace> : Ring

* The operation is equivalent to sum of [this] copies of [other]. */ public operator fun Int.times(other: P): P = multiplyBySquaring(other, this) - // endregion - // region Constant-constant relation /** * Returns the same constant. */ @@ -178,9 +169,7 @@ public interface AbstractPolynomialSpace> : Ring

* Instance of unit constant (unit of the underlying ring). */ public val constantOne: C - // endregion - // region Constant-polynomial relation /** * Returns sum of the constant represented as polynomial and the polynomial. */ @@ -193,9 +182,7 @@ public interface AbstractPolynomialSpace> : Ring

* Returns product of the constant represented as polynomial and the polynomial. */ public operator fun C.times(other: P): P - // endregion - // region Polynomial-constant relation /** * Returns sum of the constant represented as polynomial and the polynomial. */ @@ -208,9 +195,7 @@ public interface AbstractPolynomialSpace> : Ring

* Returns product of the constant represented as polynomial and the polynomial. */ public operator fun P.times(other: C): P - // endregion - // region Polynomial-polynomial relation /** * Returns the same polynomial. */ @@ -278,10 +263,7 @@ public interface AbstractPolynomialSpace> : Ring

* Checks NOT equality of the polynomials. */ public infix fun P.notEqualsTo(other: P): Boolean = !(this equalsTo other) - // endregion - // Not sure is it necessary... - // region Polynomial properties /** * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is * zero, degree is -1. @@ -314,12 +296,9 @@ public interface AbstractPolynomialSpace> : Ring

* Otherwise, (when the polynomial is not constant polynomial) raises corresponding exception. */ public fun P.asConstant(): C = asConstantOrNull() ?: error("Can not represent non-constant polynomial as a constant") - // endregion - // region Legacy of Ring interface override fun add(left: P, right: P): P = left + right override fun multiply(left: P, right: P): P = left * right - // endregion } /** @@ -335,7 +314,6 @@ public interface AbstractPolynomialSpaceOverRing, A: public val ring: A - // region Constant-integer relation /** * Returns sum of the constant and the integer represented as constant (member of underlying ring). * @@ -354,9 +332,7 @@ public interface AbstractPolynomialSpaceOverRing, A: * The operation is equivalent to sum of [other] copies of [this]. */ public override operator fun C.times(other: Int): C = ring { multiplyBySquaring(this@times, other) } - // endregion - // region Integer-constant relation /** * Returns sum of the integer represented as constant (member of underlying ring) and the constant. * @@ -375,9 +351,7 @@ public interface AbstractPolynomialSpaceOverRing, A: * The operation is equivalent to sum of [this] copies of [other]. */ public override operator fun Int.times(other: C): C = ring { multiplyBySquaring(other, this@times) } - // endregion - // region Constant-constant relation /** * Returns negation of the constant. */ @@ -412,5 +386,4 @@ public interface AbstractPolynomialSpaceOverRing, A: * Instance of unit constant (unit of the underlying ring). */ public override val constantOne: C get() = ring.one - // endregion } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt index c6f1d7a7a..b9ca01da4 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt @@ -30,7 +30,6 @@ public interface AbstractRationalFunction> { */ // TODO: Add support of field @Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") public interface AbstractRationalFunctionalSpace, R: AbstractRationalFunction> : Ring { - // region Constant-integer relation /** * Returns sum of the constant and the integer represented as constant (member of underlying ring). * @@ -49,9 +48,7 @@ public interface AbstractRationalFunctionalSpace, R: * The operation is equivalent to sum of [other] copies of [this]. */ public operator fun C.times(other: Int): C - // endregion - // region Integer-constant relation /** * Returns sum of the integer represented as constant (member of underlying ring) and the constant. * @@ -70,9 +67,7 @@ public interface AbstractRationalFunctionalSpace, R: * The operation is equivalent to sum of [this] copies of [other]. */ public operator fun Int.times(other: C): C - // endregion - // region Polynomial-integer relation /** * Returns sum of the constant and the integer represented as polynomial. * @@ -91,9 +86,7 @@ public interface AbstractRationalFunctionalSpace, R: * The operation is equivalent to sum of [other] copies of [this]. */ public operator fun P.times(other: Int): P - // endregion - // region Integer-polynomial relation /** * Returns sum of the integer represented as polynomial and the constant. * @@ -112,9 +105,7 @@ public interface AbstractRationalFunctionalSpace, R: * The operation is equivalent to sum of [this] copies of [other]. */ public operator fun Int.times(other: P): P - // endregion - // region Rational-integer relation /** * Returns sum of the rational function and the integer represented as rational function. * @@ -133,9 +124,7 @@ public interface AbstractRationalFunctionalSpace, R: * The operation is equivalent to sum of [other] copies of [this]. */ public operator fun R.times(other: Int): R = multiplyBySquaring(this, other) - // endregion - // region Integer-Rational relation /** * Returns sum of the integer represented as rational function and the rational function. * @@ -154,9 +143,7 @@ public interface AbstractRationalFunctionalSpace, R: * The operation is equivalent to sum of [this] copies of [other]. */ public operator fun Int.times(other: R): R = multiplyBySquaring(other, this) - // endregion - // region Constant-constant relation /** * Returns the same constant. */ @@ -227,9 +214,7 @@ public interface AbstractRationalFunctionalSpace, R: * Instance of unit constant (unit of the underlying ring). */ public val constantOne: C - // endregion - // region Constant-polynomial relation /** * Returns sum of the constant represented as polynomial and the polynomial. */ @@ -242,9 +227,7 @@ public interface AbstractRationalFunctionalSpace, R: * Returns product of the constant represented as polynomial and the polynomial. */ public operator fun C.times(other: P): P - // endregion - // region Polynomial-constant relation /** * Returns sum of the constant represented as polynomial and the polynomial. */ @@ -257,9 +240,7 @@ public interface AbstractRationalFunctionalSpace, R: * Returns product of the constant represented as polynomial and the polynomial. */ public operator fun P.times(other: C): P - // endregion - // region Polynomial-polynomial relation /** * Returns the same polynomial. */ @@ -327,9 +308,7 @@ public interface AbstractRationalFunctionalSpace, R: * Checks NOT equality of the polynomials. */ public infix fun P.notEqualsTo(other: P): Boolean = !(this equalsTo other) - // endregion - // region Constant-rational relation /** * Returns sum of the constant represented as rational function and the rational function. */ @@ -342,9 +321,7 @@ public interface AbstractRationalFunctionalSpace, R: * Returns product of the constant represented as polynomial and the rational function. */ public operator fun C.times(other: R): R - // endregion - // region Rational-constant relation /** * Returns sum of the constant represented as rational function and the rational function. */ @@ -357,9 +334,7 @@ public interface AbstractRationalFunctionalSpace, R: * Returns product of the constant represented as rational function and the rational function. */ public operator fun R.times(other: C): R - // endregion - // region Polynomial-rational relation /** * Returns sum of the polynomial represented as rational function and the rational function. */ @@ -372,9 +347,7 @@ public interface AbstractRationalFunctionalSpace, R: * Returns product of the polynomial represented as polynomial and the rational function. */ public operator fun P.times(other: R): R - // endregion - // region Rational-polynomial relation /** * Returns sum of the polynomial represented as rational function and the rational function. */ @@ -387,9 +360,7 @@ public interface AbstractRationalFunctionalSpace, R: * Returns product of the polynomial represented as rational function and the rational function. */ public operator fun R.times(other: P): R - // endregion - // region Rational-rational relation /** * Returns the same rational function. */ @@ -457,10 +428,7 @@ public interface AbstractRationalFunctionalSpace, R: * Checks NOT equality of the polynomials. */ public infix fun R.notEqualsTo(other: R): Boolean = !(this equalsTo other) - // endregion - // Not sure is it necessary... - // region Polynomial properties /** * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is * zero, degree is -1. @@ -494,10 +462,6 @@ public interface AbstractRationalFunctionalSpace, R: */ public fun P.asConstant(): C = asConstantOrNull() ?: error("Can not represent non-constant polynomial as a constant") - // endregion - - // Not sure is it necessary... - // region Rational properties /** * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is * zero, degree is -1. @@ -509,25 +473,8 @@ public interface AbstractRationalFunctionalSpace, R: */ public val R.denominatorDegree: Int get() = denominator.degree - // TODO: Перенести в реализацию -// fun R.substitute(argument: C): C -// fun R.substitute(argument: P): R -// fun R.substitute(argument: R): R -// -// fun R.asFunction(): (C) -> C = /*this::substitute*/ { this.substitute(it) } -// fun R.asFunctionOnConstants(): (C) -> C = /*this::substitute*/ { this.substitute(it) } -// fun P.asFunctionOnPolynomials(): (P) -> R = /*this::substitute*/ { this.substitute(it) } -// fun R.asFunctionOnRationalFunctions(): (R) -> R = /*this::substitute*/ { this.substitute(it) } -// -// operator fun R.invoke(argument: C): C = this.substitute(argument) -// operator fun R.invoke(argument: P): R = this.substitute(argument) -// operator fun R.invoke(argument: R): R = this.substitute(argument) - // endregion - - // region Legacy override fun add(left: R, right: R): R = left + right override fun multiply(left: R, right: R): R = left * right - // endregion } /** @@ -544,7 +491,6 @@ public interface AbstractRationalFunctionalSpaceOverRing.cleanUp() = filterValues { it > 0U } -// endregion - -// region Constructors and converters - //context(LabeledPolynomialSpace>) //@Suppress("FunctionName") //internal fun LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = false) : LabeledPolynomial { @@ -128,8 +122,6 @@ internal fun Map.cleanUp() = filterValues { it > 0U } public fun C.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to this)) -// endregion - /** * Space of polynomials. * @@ -140,8 +132,6 @@ public fun C.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomia public class LabeledPolynomialSpace>( public override val ring: A, ) : AbstractPolynomialSpaceOverRing, A> { - - // region Symbol-integer relation public operator fun Symbol.plus(other: Int): LabeledPolynomial = if (other == 0) LabeledPolynomial(mapOf( mapOf(this@plus to 1U) to constantOne, @@ -163,9 +153,7 @@ public class LabeledPolynomialSpace>( else LabeledPolynomial(mapOf( mapOf(this to 1U) to constantOne * other, )) - // endregion - // region Integer-variable relation public operator fun Int.plus(other: Symbol): LabeledPolynomial = if (this == 0) LabeledPolynomial(mapOf( mapOf(other to 1U) to constantOne, @@ -187,9 +175,7 @@ public class LabeledPolynomialSpace>( else LabeledPolynomial(mapOf( mapOf(other to 1U) to constantOne * this@times, )) - // endregion - // region Polynomial-integer relation /** * Returns sum of the polynomial and the integer represented as polynomial. * @@ -243,9 +229,7 @@ public class LabeledPolynomialSpace>( mapValues { (_, c) -> c * other } } ) - // endregion - // region Integer-polynomial relation /** * Returns sum of the integer represented as polynomial and the polynomial. * @@ -299,9 +283,7 @@ public class LabeledPolynomialSpace>( mapValues { (_, c) -> this@times * c } } ) - // endregion - // region Constant-variable relation public operator fun C.plus(other: Symbol): LabeledPolynomial = if (isZero()) LabeledPolynomial(mapOf( mapOf(other to 1U) to constantOne, @@ -323,9 +305,7 @@ public class LabeledPolynomialSpace>( else LabeledPolynomial(mapOf( mapOf(other to 1U) to this@times, )) - // endregion - // region Symbol-constant relation public operator fun Symbol.plus(other: C): LabeledPolynomial = if (other.isZero()) LabeledPolynomial(mapOf( mapOf(this@plus to 1U) to constantOne, @@ -347,9 +327,7 @@ public class LabeledPolynomialSpace>( else LabeledPolynomial(mapOf( mapOf(this@times to 1U) to other, )) - // endregion - // region Constant-polynomial relation /** * Returns sum of the constant represented as polynomial and the polynomial. */ @@ -401,9 +379,7 @@ public class LabeledPolynomialSpace>( mapValues { (_, c) -> this@times * c } } ) - // endregion - // region Polynomial-constant relation /** * Returns sum of the constant represented as polynomial and the polynomial. */ @@ -455,9 +431,7 @@ public class LabeledPolynomialSpace>( mapValues { (_, c) -> c * other } } ) - // endregion - // region Symbol-variable relation public operator fun Symbol.plus(other: Symbol): LabeledPolynomial = if (this == other) LabeledPolynomial(mapOf( mapOf(this to 1U) to constantOne * 2 @@ -479,9 +453,7 @@ public class LabeledPolynomialSpace>( else LabeledPolynomial(mapOf( mapOf(this to 1U, other to 1U) to constantOne, )) - // endregion - // region Symbol-polynomial relation public operator fun Symbol.plus(other: LabeledPolynomial): LabeledPolynomial = with(other.coefficients) { if (isEmpty()) LabeledPolynomial(mapOf(mapOf(this@plus to 1u) to constantOne)) @@ -519,9 +491,7 @@ public class LabeledPolynomialSpace>( other.coefficients .mapKeys { (degs, _) -> degs.toMutableMap().also{ it[this] = if (this in it) it[this]!! + 1U else 1U } } ) - // endregion - // region Polynomial-variable relation public operator fun LabeledPolynomial.plus(other: Symbol): LabeledPolynomial = with(coefficients) { if (isEmpty()) LabeledPolynomial(mapOf(mapOf(other to 1u) to constantOne)) @@ -557,9 +527,7 @@ public class LabeledPolynomialSpace>( coefficients .mapKeys { (degs, _) -> degs.toMutableMap().also{ it[other] = if (other in it) it[other]!! + 1U else 1U } } ) - // endregion - // region Polynomial-polynomial relation /** * Returns negation of the polynomial. */ @@ -626,10 +594,7 @@ public class LabeledPolynomialSpace>( else -> coefficients.size == other.coefficients.size && coefficients.all { (key, value) -> with(other.coefficients) { key in this && this[key] == value } } } - // endregion - // Not sure is it necessary... - // region Polynomial properties /** * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is * zero, degree is -1. @@ -713,10 +678,8 @@ public class LabeledPolynomialSpace>( // @Suppress("NOTHING_TO_INLINE") // @JvmName("invokePolynomial") // public inline operator fun LabeledPolynomial.invoke(argument: Map>): LabeledPolynomial = this.substitute(ring, argument) - // endregion - // region Utilities - // TODO: Move to region internal utilities with context receiver + // TODO: Move to other internal utilities with context receiver @JvmName("applyAndRemoveZerosInternal") internal fun MutableMap, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : MutableMap, C> { contract { @@ -744,5 +707,4 @@ public class LabeledPolynomialSpace>( for ((degs, c) in this) if (c.isZero()) this.remove(degs) } } - // endregion } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt index 3077a2b82..3908933e6 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt @@ -17,8 +17,6 @@ public class LabeledRationalFunction( override fun toString(): String = "LabeledRationalFunction${numerator.coefficients}/${denominator.coefficients}" } -// region Internal utilities - /** * Represents internal [LabeledRationalFunction] errors. */ @@ -34,9 +32,6 @@ internal class LabeledRationalFunctionError : Error { */ internal fun labeledRationalFunctionError(message: Any): Nothing = throw LabeledRationalFunctionError(message.toString()) -// endregion - -// region Constructors and converters // Waiting for context receivers :( TODO: Replace with context receivers when they will be available //context(RationalFunctionSpace) @@ -82,8 +77,6 @@ internal fun labeledRationalFunctionError(message: Any): Nothing = throw Labeled //LabeledPolynomial(numeratorCoefficients) //) -// endregion - public class LabeledRationalFunctionSpace>( public val ring: A, ) : AbstractRationalFunctionalSpaceOverPolynomialSpace< @@ -95,7 +88,6 @@ public class LabeledRationalFunctionSpace>( override val polynomialRing : LabeledPolynomialSpace = LabeledPolynomialSpace(ring) - // region Rational-integer relation /** * Returns sum of the rational function and the integer represented as rational function. * @@ -126,9 +118,7 @@ public class LabeledRationalFunctionSpace>( numerator * other, denominator ) - // endregion - // region Integer-Rational relation /** * Returns sum of the integer represented as rational function and the rational function. * @@ -159,9 +149,7 @@ public class LabeledRationalFunctionSpace>( this * other.numerator, other.denominator ) - // endregion - // region Constant-rational relation /** * Returns sum of the constant represented as rational function and the rational function. */ @@ -186,9 +174,7 @@ public class LabeledRationalFunctionSpace>( this * other.numerator, other.denominator ) - // endregion - // region Rational-constant relation /** * Returns sum of the constant represented as rational function and the rational function. */ @@ -213,9 +199,7 @@ public class LabeledRationalFunctionSpace>( numerator * other, denominator ) - // endregion - // region Polynomial-rational relation /** * Returns sum of the polynomial represented as rational function and the rational function. */ @@ -240,9 +224,7 @@ public class LabeledRationalFunctionSpace>( this * other.numerator, other.denominator ) - // endregion - // region Rational-polynomial relation /** * Returns sum of the polynomial represented as rational function and the rational function. */ @@ -267,9 +249,7 @@ public class LabeledRationalFunctionSpace>( numerator * other, denominator ) - // endregion - // region Rational-rational relation /** * Returns negation of the rational function. */ @@ -329,9 +309,7 @@ public class LabeledRationalFunctionSpace>( return numerator * other.denominator equalsTo other.numerator * denominator } - // endregion - // region Polynomial properties /** * Map that associates variables (that appear in the polynomial in positive exponents) with their most exponents * in which they are appeared in the polynomial. @@ -348,9 +326,7 @@ public class LabeledRationalFunctionSpace>( * Count of all variables that appear in the polynomial in positive exponents. */ public val LabeledPolynomial.countOfVariables: Int get() = polynomialRing { countOfVariables } - // endregion - // region Rational properties /** * Count of all variables that appear in the polynomial in positive exponents. */ @@ -360,9 +336,8 @@ public class LabeledRationalFunctionSpace>( * Count of all variables that appear in the polynomial in positive exponents. */ public val LabeledRationalFunction.countOfVariables: Int get() = variables.size - // endregion - // region REST TODO: Разобрать + // TODO: Разобрать public operator fun LabeledRationalFunction.div(other: LabeledRationalFunction): LabeledRationalFunction = LabeledRationalFunction( diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index a1033fcc4..fe6bb597d 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -47,8 +47,6 @@ internal constructor( override fun toString(): String = "NumberedPolynomial$coefficients" } -// region Internal utilities - /** * Represents internal [Polynomial] errors. */ @@ -69,10 +67,6 @@ internal fun numberedPolynomialError(message: Any): Nothing = throw PolynomialEr */ internal fun List.cleanUp() = subList(0, indexOfLast { it != 0U } + 1) -// endregion - -// region Constructors and converters - //context(NumberedPolynomialSpace>) //@Suppress("FunctionName") //internal fun NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = false) : NumberedPolynomial { @@ -124,8 +118,6 @@ internal fun List.cleanUp() = subList(0, indexOfLast { it != 0U } + 1) public fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(emptyList() to this)) -// endregion - /** * Space of polynomials. * @@ -136,7 +128,6 @@ public fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolyno public open class NumberedPolynomialSpace>( public final override val ring: A, ) : AbstractPolynomialSpaceOverRing, A> { - // region Polynomial-integer relation /** * Returns sum of the polynomial and the integer represented as polynomial. * @@ -190,9 +181,7 @@ public open class NumberedPolynomialSpace>( mapValues { (_, c) -> c * other } } ) - // endregion - // region Integer-polynomial relation /** * Returns sum of the integer represented as polynomial and the polynomial. * @@ -246,9 +235,7 @@ public open class NumberedPolynomialSpace>( mapValues { (_, c) -> this@times * c } } ) - // endregion - // region Constant-polynomial relation /** * Returns sum of the constant represented as polynomial and the polynomial. */ @@ -300,9 +287,7 @@ public open class NumberedPolynomialSpace>( mapValues { (_, c) -> this@times * c } } ) - // endregion - // region Polynomial-constant relation /** * Returns sum of the constant represented as polynomial and the polynomial. */ @@ -352,9 +337,7 @@ public open class NumberedPolynomialSpace>( mapValues { (_, c) -> c * other } } ) - // endregion - // region Polynomial-polynomial relation /** * Returns negation of the polynomial. */ @@ -463,10 +446,7 @@ public open class NumberedPolynomialSpace>( else -> coefficients.size == other.coefficients.size && coefficients.all { (key, value) -> with(other.coefficients) { key in this && this[key] == value } } } - // endregion - // Not sure is it necessary... - // region Polynomial properties // TODO: Replace `countOfVariables` with `lastVariable` and create new `countOfVariables` /** * Count of all variables that appear in the polynomial in positive exponents. @@ -545,10 +525,8 @@ public open class NumberedPolynomialSpace>( @Suppress("NOTHING_TO_INLINE") @JvmName("invokePolynomial") public inline operator fun NumberedPolynomial.invoke(argument: Map>): NumberedPolynomial = this.substitute(ring, argument) - // endregion - // region Utilities - // TODO: Move to region internal utilities with context receiver + // TODO: Move to other internal utilities with context receiver @JvmName("applyAndRemoveZerosInternal") internal fun MutableMap, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : MutableMap, C> { contract { @@ -576,9 +554,6 @@ public open class NumberedPolynomialSpace>( for ((degs, c) in this) if (c.isZero()) this.remove(degs) } } - // endregion - - // region Constructors and converters @Suppress("FunctionName") internal fun NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = false) : NumberedPolynomial { @@ -622,6 +597,4 @@ public open class NumberedPolynomialSpace>( @Suppress("FunctionName") public fun NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(pairs.toList(), toCheckInput = true) - - // endregion } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt index a81795c81..745df10e8 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt @@ -16,8 +16,6 @@ public class NumberedRationalFunction internal constructor( override fun toString(): String = "NumberedRationalFunction${numerator.coefficients}/${denominator.coefficients}" } -// region Internal utilities - /** * Represents internal [NumberedRationalFunction] errors. */ @@ -33,9 +31,6 @@ internal class NumberedRationalFunctionError : Error { */ internal fun numberedRationalFunctionError(message: Any): Nothing = throw NumberedRationalFunctionError(message.toString()) -// endregion - -// region Constructors and converters // Waiting for context receivers :( TODO: Replace with context receivers when they will be available //context(RationalFunctionSpace) @@ -78,8 +73,6 @@ internal fun numberedRationalFunctionError(message: Any): Nothing = throw Number //Polynomial(numeratorCoefficients) //) -// endregion - public class NumberedRationalFunctionSpace> ( public val ring: A, ) : AbstractRationalFunctionalSpaceOverPolynomialSpace< @@ -91,7 +84,6 @@ public class NumberedRationalFunctionSpace> ( override val polynomialRing : NumberedPolynomialSpace = NumberedPolynomialSpace(ring) - // region Rational-integer relation /** * Returns sum of the rational function and the integer represented as rational function. * @@ -122,9 +114,7 @@ public class NumberedRationalFunctionSpace> ( numerator * other, denominator ) - // endregion - // region Integer-Rational relation /** * Returns sum of the integer represented as rational function and the rational function. * @@ -155,9 +145,7 @@ public class NumberedRationalFunctionSpace> ( this * other.numerator, other.denominator ) - // endregion - // region Constant-rational relation /** * Returns sum of the constant represented as rational function and the rational function. */ @@ -182,9 +170,7 @@ public class NumberedRationalFunctionSpace> ( this * other.numerator, other.denominator ) - // endregion - // region Rational-constant relation /** * Returns sum of the constant represented as rational function and the rational function. */ @@ -209,9 +195,7 @@ public class NumberedRationalFunctionSpace> ( numerator * other, denominator ) - // endregion - // region Polynomial-rational relation /** * Returns sum of the polynomial represented as rational function and the rational function. */ @@ -236,9 +220,7 @@ public class NumberedRationalFunctionSpace> ( this * other.numerator, other.denominator ) - // endregion - // region Rational-polynomial relation /** * Returns sum of the polynomial represented as rational function and the rational function. */ @@ -263,9 +245,7 @@ public class NumberedRationalFunctionSpace> ( numerator * other, denominator ) - // endregion - // region Rational-rational relation /** * Returns negation of the rational function. */ @@ -325,9 +305,7 @@ public class NumberedRationalFunctionSpace> ( return numerator * other.denominator equalsTo other.numerator * denominator } - // endregion - // region Polynomial properties /** * Count of all variables that appear in the polynomial in positive exponents. */ @@ -340,17 +318,14 @@ public class NumberedRationalFunctionSpace> ( * And size of the list is [countOfVariables]. */ public val NumberedPolynomial.degrees: List get() = polynomialRing { degrees } - // endregion - // region Rational properties /** * Count of all variables that appear in the polynomial in positive exponents. */ public val NumberedRationalFunction.countOfVariables: Int get() = polynomialRing { max(numerator.countOfVariables, denominator.countOfVariables) } - // endregion - // region REST TODO: Разобрать + // TODO: Разобрать public operator fun NumberedRationalFunction.div(other: NumberedRationalFunction): NumberedRationalFunction = NumberedRationalFunction( diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 2f7976da6..3f3838f53 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -91,7 +91,6 @@ public fun C.asPolynomial() : Polynomial = Polynomial(listOf(this)) * @param A type of underlying ring of constants. It's [Ring] of [C]. * @param ring underlying ring of constants of type [A]. */ -//@Suppress("INAPPLICABLE_JVM_NAME") // TODO: KT-31420 public open class PolynomialSpace>( public override val ring: A, ) : AbstractPolynomialSpaceOverRing, A> { diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index 441136a64..5ff3edd2e 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -18,8 +18,6 @@ public data class RationalFunction internal constructor ( override fun toString(): String = "RationalFunction${numerator.coefficients}/${denominator.coefficients}" } -// region Internal utilities - /** * Represents internal [RationalFunction] errors. */ @@ -35,9 +33,6 @@ internal class RationalFunctionError : Error { */ internal fun rationalFunctionError(message: Any): Nothing = throw RationalFunctionError(message.toString()) -// endregion - -// region Constructors and converters // Waiting for context receivers :( TODO: Replace with context receivers when they will be available //context(RationalFunctionSpace) @@ -63,8 +58,6 @@ internal fun rationalFunctionError(message: Any): Nothing = throw RationalFuncti // Polynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ) // ) -// endregion - public class RationalFunctionSpace> ( public val ring: A, ) : AbstractRationalFunctionalSpaceOverPolynomialSpace< @@ -76,7 +69,6 @@ public class RationalFunctionSpace> ( override val polynomialRing : PolynomialSpace = PolynomialSpace(ring) - // region Rational-integer relation /** * Returns sum of the rational function and the integer represented as rational function. * @@ -107,9 +99,7 @@ public class RationalFunctionSpace> ( numerator * other, denominator ) - // endregion - // region Integer-Rational relation /** * Returns sum of the integer represented as rational function and the rational function. * @@ -140,9 +130,7 @@ public class RationalFunctionSpace> ( this * other.numerator, other.denominator ) - // endregion - // region Constant-rational relation /** * Returns sum of the constant represented as rational function and the rational function. */ @@ -167,9 +155,7 @@ public class RationalFunctionSpace> ( this * other.numerator, other.denominator ) - // endregion - // region Rational-constant relation /** * Returns sum of the constant represented as rational function and the rational function. */ @@ -194,9 +180,7 @@ public class RationalFunctionSpace> ( numerator * other, denominator ) - // endregion - // region Polynomial-rational relation /** * Returns sum of the polynomial represented as rational function and the rational function. */ @@ -221,9 +205,7 @@ public class RationalFunctionSpace> ( this * other.numerator, other.denominator ) - // endregion - // region Rational-polynomial relation /** * Returns sum of the polynomial represented as rational function and the rational function. */ @@ -248,9 +230,7 @@ public class RationalFunctionSpace> ( numerator * other, denominator ) - // endregion - // region Rational-rational relation /** * Returns negation of the rational function. */ @@ -298,9 +278,8 @@ public class RationalFunctionSpace> ( numeratorDegree - denominatorDegree != with(other) { numeratorDegree - denominatorDegree } -> false else -> numerator * other.denominator equalsTo other.numerator * denominator } - // endregion - // region REST TODO: Разобрать + // TODO: Разобрать public operator fun RationalFunction.div(other: RationalFunction): RationalFunction = RationalFunction( @@ -383,5 +362,4 @@ public class RationalFunctionSpace> ( // numerator.removeZeros(), // denominator.removeZeros() // ) - // endregion } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt index 516e76b8f..19417d767 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt @@ -17,10 +17,6 @@ import kotlin.contracts.contract // TODO: Docs -// region Sort of legacy - -//// region Constants -// //// TODO: Reuse underlying ring extensions // //context(LabeledPolynomialSpace) @@ -33,9 +29,7 @@ import kotlin.contracts.contract //context(LabeledPolynomialSpace) //fun > multiplyWithPower(base: C, arg: C, pow: UInt): C = ring { multiplyWithPower(base, arg, pow) } // -//// endregion -//// region Symbols // //context(LabeledPolynomialSpace) //fun > power(arg: Symbol, pow: UInt): LabeledPolynomial = @@ -44,9 +38,7 @@ import kotlin.contracts.contract // mapOf(arg to pow) to constantOne // )) // -//// endregion -//// region Polynomials // //context(LabeledPolynomialSpace) //fun > number(value: Int): LabeledPolynomial = ring { LabeledPolynomial(mapOf(emptyMap() to number(value))) } @@ -71,11 +63,6 @@ import kotlin.contracts.contract // else -> error("Error in raising ring instant by unsigned integer: got reminder by division by 2 different from 0 and 1") // } // -//// endregion - -// endregion - -// region Utilities /** * Crates a [LabeledPolynomialSpace] over received ring. @@ -92,10 +79,6 @@ public inline fun , R> A.labeledPolynomial(block: LabeledPolynomi return LabeledPolynomialSpace(this).block() } -// endregion - -//// region String representations -// ///** // * Represents the polynomial as a [String] with names of variables substituted with names from [names]. // * Consider that monomials are sorted in lexicographic order. @@ -261,13 +244,7 @@ public inline fun , R> A.labeledPolynomial(block: LabeledPolynomi //context(LabeledPolynomialSpace) //fun > LabeledPolynomial.representReversedWithBrackets(namer: (Symbol) -> String): String = // with(representReversed(namer)) { if (coefficients.count() == 1) this else "($this)" } -// -//// endregion -// region Operator extensions - -//// region Field case -// //operator fun > Polynomial.div(other: T): Polynomial = // if (other.isZero()) throw ArithmeticException("/ by zero") // else @@ -276,13 +253,7 @@ public inline fun , R> A.labeledPolynomial(block: LabeledPolynomi // .mapValues { it.value / other }, // toCheckInput = false // ) -// -//// endregion -// endregion - -//// region Polynomial substitution and functional representation -// //public fun LabeledPolynomial.substitute(ring: Ring, args: Map): LabeledPolynomial = ring { // if (coefficients.isEmpty()) return this@substitute // LabeledPolynomial( @@ -324,10 +295,6 @@ public inline fun , R> A.labeledPolynomial(block: LabeledPolynomi // //fun > LabeledPolynomial.asPolynomialFunctionOver(ring: A): (Map>) -> LabeledPolynomial = // { substitute(ring, it) } -// -//// endregion - -// region Algebraic derivative and antiderivative /** * Returns algebraic derivative of received polynomial. @@ -572,6 +539,4 @@ public fun > LabeledPolynomial.nthAntiderivativeWithRespectTo } } ) -} - -// endregion \ No newline at end of file +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt index 575dfed48..61f443871 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt @@ -6,18 +6,10 @@ package space.kscience.kmath.functions -//// region Operator extensions -// -//// region Field case -// //fun > LabeledRationalFunction.reduced(): LabeledRationalFunction { // val greatestCommonDivider = polynomialGCD(numerator, denominator) // return LabeledRationalFunction( // numerator / greatestCommonDivider, // denominator / greatestCommonDivider // ) -//} -// -//// endregion -// -//// endregion \ No newline at end of file +//} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt index ac411fc28..b2778343d 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt @@ -9,10 +9,6 @@ import kotlin.math.max // TODO: Docs -// region Sort of legacy - -//// region Constants -// //// TODO: Reuse underlying ring extensions // //context(NumberedPolynomialSpace) @@ -21,11 +17,7 @@ import kotlin.math.max // //context(NumberedPolynomialSpace) //public fun > multiplyWithPower(base: C, arg: C, pow: UInt): C = ring { multiplyWithPower(base, arg, pow) } -// -//// endregion -//// region Polynomials -// //context(NumberedPolynomialSpace) //public fun > number(value: Int): NumberedPolynomial = ring { NumberedPolynomial(mapOf(emptyList() to number(value))) } // @@ -48,12 +40,6 @@ import kotlin.math.max // exponent % 2U == 1U -> multiplyWithPowerInternalLogic(base * arg, arg * arg, exponent / 2U) // else -> error("Error in raising ring instant by unsigned integer: got reminder by division by 2 different from 0 and 1") // } -// -//// endregion - -// endregion - -// region Utilities /** * Crates a [NumberedPolynomialSpace] over received ring. @@ -70,10 +56,6 @@ public inline fun , R> A.numberedPolynomial(block: NumberedPolyno return NumberedPolynomialSpace(this).block() } -// endregion - -//// region String representations -// ///** // * Represents the polynomial as a [String] where name of variable with index `i` is [withVariableName] + `"_${i+1}"`. // * Consider that monomials are sorted in lexicographic order. @@ -237,11 +219,7 @@ public inline fun , R> A.numberedPolynomial(block: NumberedPolyno //context(NumberedPolynomialSpace) //public fun > NumberedPolynomial.representReversedWithBrackets(namer: (Int) -> String): String = // with(representReversed(namer)) { if (coefficients.count() == 1) this else "($this)" } -// -//// endregion -//// region Polynomial substitution and functional representation -// //public fun NumberedPolynomial.substitute(ring: Ring, args: Map): NumberedPolynomial = ring { // if (coefficients.isEmpty()) return this@substitute // NumberedPolynomial( @@ -283,13 +261,7 @@ public inline fun , R> A.numberedPolynomial(block: NumberedPolyno // //public fun > NumberedPolynomial.asPolynomialFunctionOver(ring: A): (Map>) -> NumberedPolynomial = // { substitute(ring, it) } -// -//// endregion -// region Operator extensions - -//// region Field case -// //operator fun > Polynomial.div(other: T): Polynomial = // if (other.isZero()) throw ArithmeticException("/ by zero") // else @@ -298,12 +270,6 @@ public inline fun , R> A.numberedPolynomial(block: NumberedPolyno // .mapValues { it.value / other }, // toCheckInput = false // ) -// -//// endregion - -// endregion - -// region Polynomial substitution and functional representation // TODO: May be apply Horner's method too? /** @@ -368,10 +334,6 @@ public fun > NumberedPolynomial.asFunction(ring: A): (Map> NumberedPolynomial.asPolynomialFunctionOver(ring: A): (Map>) -> NumberedPolynomial = { substitute(ring, it) } -// endregion - -// region Algebraic derivative and antiderivative - /** * Returns algebraic derivative of received polynomial. */ @@ -596,6 +558,4 @@ public fun > NumberedPolynomial.nthAntiderivativeWithRespectT } } ) -} - -// endregion \ No newline at end of file +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt index 7c8120c68..035e201f7 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt @@ -6,18 +6,10 @@ package space.kscience.kmath.functions -//// region Operator extensions -// -//// region Field case -// //fun > NumberedRationalFunction.reduced(): NumberedRationalFunction { // val greatestCommonDivider = polynomialGCD(numerator, denominator) // return NumberedRationalFunction( // numerator / greatestCommonDivider, // denominator / greatestCommonDivider // ) -//} -// -//// endregion -// -//// endregion \ No newline at end of file +//} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt index 2d0377d2c..e6d6b1ae6 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt @@ -14,8 +14,6 @@ import kotlin.math.min import kotlin.math.pow -// region Utilities - /** * Removes zeros on the end of the coefficient list of polynomial. */ @@ -51,10 +49,6 @@ public inline fun A.scalablePolynomial(block: ScalablePolynomialSpace< return ScalablePolynomialSpace(this).block() } -// endregion - -// region Polynomial substitution and functional representation - // TODO: May be apply Horner's method too? /** * Evaluates the value of the given double polynomial for given double argument. @@ -116,10 +110,6 @@ public fun > Polynomial.asFunction(ring: A): (C) -> C = { subs */ public fun > Polynomial.asPolynomialFunctionOver(ring: A): (Polynomial) -> Polynomial = { substitute(ring, it) } -// endregion - -// region Algebraic derivative and antiderivative - /** * Returns algebraic derivative of received polynomial. */ @@ -180,6 +170,4 @@ public fun > Polynomial.integrate( ): C = algebra { val integral = antiderivative(algebra) integral.substitute(algebra, range.endInclusive) - integral.substitute(algebra, range.start) -} - -// endregion \ No newline at end of file +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/rationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/rationalFunctionUtil.kt index d5bbc3b82..359c781b5 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/rationalFunctionUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/rationalFunctionUtil.kt @@ -6,10 +6,6 @@ package space.kscience.kmath.functions -// region Operator extensions - -// region Field case - //operator fun > RationalFunction.invoke(arg: T): T = numerator(arg) / denominator(arg) // //fun > RationalFunction.reduced(): RationalFunction = @@ -20,11 +16,6 @@ package space.kscience.kmath.functions // ) // } -// endregion - -// endregion - -// region Derivatives ///** // * Returns result of applying formal derivative to the polynomial. // * @@ -35,5 +26,4 @@ package space.kscience.kmath.functions // RationalFunction( // numerator.derivative() * denominator - denominator.derivative() * numerator, // denominator * denominator -// ) -// endregion \ No newline at end of file +// ) \ No newline at end of file -- 2.34.1 From 75fd9207352c2cdbd4ad4de1275a0f8639f83f76 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Wed, 16 Mar 2022 23:22:51 +0300 Subject: [PATCH 035/275] Deleted suddenly missed region marks and unused error classes --- .../kmath/functions/LabeledPolynomial.kt | 15 -------- .../functions/LabeledRationalFunction.kt | 15 -------- .../kmath/functions/NumberedPolynomial.kt | 17 +-------- .../functions/NumberedRationalFunction.kt | 15 -------- .../kscience/kmath/functions/Polynomial.kt | 37 ------------------- .../kmath/functions/RationalFunction.kt | 15 -------- 6 files changed, 1 insertion(+), 113 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt index f4dd74b94..d263b7102 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -48,21 +48,6 @@ internal constructor( override fun toString(): String = "LabeledPolynomial$coefficients" } -/** - * Represents internal [LabeledPolynomial] errors. - */ -internal class LabeledPolynomialError: Error { - constructor(): super() - constructor(message: String): super(message) - constructor(message: String?, cause: Throwable?): super(message, cause) - constructor(cause: Throwable?): super(cause) -} - -/** - * Throws an [LabeledPolynomialError] with the given [message]. - */ -internal fun labeledPolynomialError(message: Any): Nothing = throw LabeledPolynomialError(message.toString()) - /** * Returns the same degrees description of the monomial, but without zero degrees. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt index 3908933e6..9b5022f85 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt @@ -17,21 +17,6 @@ public class LabeledRationalFunction( override fun toString(): String = "LabeledRationalFunction${numerator.coefficients}/${denominator.coefficients}" } -/** - * Represents internal [LabeledRationalFunction] errors. - */ -internal class LabeledRationalFunctionError : Error { - constructor(): super() - constructor(message: String): super(message) - constructor(message: String?, cause: Throwable?): super(message, cause) - constructor(cause: Throwable?): super(cause) -} - -/** - * Throws an [LabeledRationalFunctionError] with the given [message]. - */ -internal fun labeledRationalFunctionError(message: Any): Nothing = throw LabeledRationalFunctionError(message.toString()) - // Waiting for context receivers :( TODO: Replace with context receivers when they will be available //context(RationalFunctionSpace) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index fe6bb597d..307b78f29 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -48,22 +48,7 @@ internal constructor( } /** - * Represents internal [Polynomial] errors. - */ -internal class NumberedPolynomialError : Error { - constructor(): super() - constructor(message: String): super(message) - constructor(message: String?, cause: Throwable?): super(message, cause) - constructor(cause: Throwable?): super(cause) -} - -/** - * Throws an [PolynomialError] with the given [message]. - */ -internal fun numberedPolynomialError(message: Any): Nothing = throw PolynomialError(message.toString()) - -/** - * Returns the same degrees description of the monomial, but without extra zero degrees on the end. + * 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) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt index 745df10e8..8e3b3b1c5 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt @@ -16,21 +16,6 @@ public class NumberedRationalFunction internal constructor( override fun toString(): String = "NumberedRationalFunction${numerator.coefficients}/${denominator.coefficients}" } -/** - * Represents internal [NumberedRationalFunction] errors. - */ -internal class NumberedRationalFunctionError : Error { - constructor(): super() - constructor(message: String): super(message) - constructor(message: String?, cause: Throwable?): super(message, cause) - constructor(cause: Throwable?): super(cause) -} - -/** - * Throws an [NumberedRationalFunctionError] with the given [message]. - */ -internal fun numberedRationalFunctionError(message: Any): Nothing = throw NumberedRationalFunctionError(message.toString()) - // Waiting for context receivers :( TODO: Replace with context receivers when they will be available //context(RationalFunctionSpace) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 3f3838f53..c6f649fe8 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -43,27 +43,6 @@ public data class Polynomial( override fun toString(): String = "Polynomial$coefficients" } -// region Internal utilities - -/** - * Represents internal [Polynomial] errors. - */ -internal class PolynomialError : Error { - constructor(): super() - constructor(message: String): super(message) - constructor(message: String?, cause: Throwable?): super(message, cause) - constructor(cause: Throwable?): super(cause) -} - -/** - * Throws an [PolynomialError] with the given [message]. - */ -internal fun polynomialError(message: Any): Nothing = throw PolynomialError(message.toString()) - -// endregion - -// region Constructors and converters - /** * Returns a [Polynomial] instance with given [coefficients]. The collection of coefficients will be reversed if * [reverse] parameter is true. @@ -82,8 +61,6 @@ public fun Polynomial(vararg coefficients: C, reverse: Boolean = false): Pol public fun C.asPolynomial() : Polynomial = Polynomial(listOf(this)) -// endregion - /** * Space of univariate polynomials constructed over ring. * @@ -94,8 +71,6 @@ public fun C.asPolynomial() : Polynomial = Polynomial(listOf(this)) public open class PolynomialSpace>( public override val ring: A, ) : AbstractPolynomialSpaceOverRing, A> { - - // region Polynomial-integer relation /** * Returns sum of the polynomial and the integer represented as polynomial. * @@ -152,9 +127,7 @@ public open class PolynomialSpace>( .subList(0, degree + 1) .map { it * other } ) - // endregion - // region Integer-polynomial relation /** * Returns sum of the integer represented as polynomial and the polynomial. * @@ -213,9 +186,7 @@ public open class PolynomialSpace>( .subList(0, other.degree + 1) .map { it * this } ) - // endregion - // region Constant-polynomial relation /** * Returns sum of the constant represented as polynomial and the polynomial. */ @@ -270,9 +241,7 @@ public open class PolynomialSpace>( .subList(0, other.degree + 1) .map { it * this } ) - // endregion - // region Polynomial-constant relation /** * Returns sum of the constant represented as polynomial and the polynomial. */ @@ -325,9 +294,7 @@ public open class PolynomialSpace>( .subList(0, degree + 1) .map { it * other } ) - // endregion - // region Polynomial-polynomial relation /** * Returns negation of the polynomial. */ @@ -425,9 +392,7 @@ public open class PolynomialSpace>( else false } } - // endregion - // region Polynomial properties /** * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is * zero, degree is -1. @@ -466,8 +431,6 @@ public open class PolynomialSpace>( public inline operator fun Polynomial.invoke(argument: C): C = this.substitute(ring, argument) @Suppress("NOTHING_TO_INLINE") public inline operator fun Polynomial.invoke(argument: Polynomial): Polynomial = this.substitute(ring, argument) - - // endregion } /** diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index 5ff3edd2e..f4ae64e81 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -18,21 +18,6 @@ public data class RationalFunction internal constructor ( override fun toString(): String = "RationalFunction${numerator.coefficients}/${denominator.coefficients}" } -/** - * Represents internal [RationalFunction] errors. - */ -internal class RationalFunctionError : Error { - constructor(): super() - constructor(message: String): super(message) - constructor(message: String?, cause: Throwable?): super(message, cause) - constructor(cause: Throwable?): super(cause) -} - -/** - * Throws an [RationalFunction] with the given [message]. - */ -internal fun rationalFunctionError(message: Any): Nothing = throw RationalFunctionError(message.toString()) - // Waiting for context receivers :( TODO: Replace with context receivers when they will be available //context(RationalFunctionSpace) -- 2.34.1 From 2082175af5e9e811d3a6dfa3079a7dcb2d25a2fe Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Wed, 16 Mar 2022 23:31:07 +0300 Subject: [PATCH 036/275] Fixed typos. --- .../kmath/functions/LabeledPolynomial.kt | 2 +- .../space/kscience/kmath/functions/Polynomial.kt | 2 +- .../kscience/kmath/functions/RationalFunction.kt | 5 +---- .../kmath/functions/labeledPolynomialUtil.kt | 4 ++-- .../kmath/functions/numberedPolynomialUtil.kt | 16 ++++++++-------- .../kscience/kmath/functions/polynomialUtil.kt | 8 ++++---- 6 files changed, 17 insertions(+), 20 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt index d263b7102..369c7078a 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -49,7 +49,7 @@ internal constructor( } /** - * Returns the same degrees description of the monomial, but without zero degrees. + * Returns the same degrees' description of the monomial, but without zero degrees. */ internal fun Map.cleanUp() = filterValues { it > 0U } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index c6f649fe8..220bde8ff 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -425,7 +425,7 @@ public open class PolynomialSpace>( public inline fun Polynomial.asFunctionOnPolynomials(): (Polynomial) -> Polynomial = { this.substitute(ring, it) } /** - * Evaluates the polynomial for the given value [arg]. + * Evaluates the polynomial for the given value [argument]. */ @Suppress("NOTHING_TO_INLINE") public inline operator fun Polynomial.invoke(argument: C): C = this.substitute(ring, argument) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index f4ae64e81..226eddce9 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -5,10 +5,7 @@ package space.kscience.kmath.functions -import space.kscience.kmath.operations.* -import kotlin.jvm.JvmName -import kotlin.math.max -import kotlin.math.min +import space.kscience.kmath.operations.Ring public data class RationalFunction internal constructor ( diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt index 19417d767..27fdd7d7b 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt @@ -65,13 +65,13 @@ import kotlin.contracts.contract // /** - * Crates a [LabeledPolynomialSpace] over received ring. + * Creates a [LabeledPolynomialSpace] over a received ring. */ public fun > A.labeledPolynomial(): LabeledPolynomialSpace = LabeledPolynomialSpace(this) /** - * Crates a [LabeledPolynomialSpace]'s scope over received ring. + * Creates a [LabeledPolynomialSpace]'s scope over a received ring. */ @OptIn(ExperimentalContracts::class) public inline fun , R> A.labeledPolynomial(block: LabeledPolynomialSpace.() -> R): R { diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt index b2778343d..d544ca93c 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt @@ -42,13 +42,13 @@ import kotlin.math.max // } /** - * Crates a [NumberedPolynomialSpace] over received ring. + * Creates a [NumberedPolynomialSpace] over a received ring. */ public fun > A.numberedPolynomial(): NumberedPolynomialSpace = NumberedPolynomialSpace(this) /** - * Crates a [NumberedPolynomialSpace]'s scope over received ring. + * Creates a [NumberedPolynomialSpace]'s scope over a received ring. */ @OptIn(ExperimentalContracts::class) public inline fun , R> A.numberedPolynomial(block: NumberedPolynomialSpace.() -> R): R { @@ -279,9 +279,9 @@ public fun NumberedPolynomial.substitute(args: Map): Number val acc = LinkedHashMap, Double>(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, substitutor) -> + val newC = args.entries.fold(c) { product, (variable, substitution) -> val deg = degs.getOrElse(variable) { 0u } - if (deg == 0u) product else product * substitutor.pow(deg.toInt()) + if (deg == 0u) product else product * substitution.pow(deg.toInt()) } if (newDegs !in acc) acc[newDegs] = newC else acc[newDegs] = acc[newDegs]!! + newC @@ -298,9 +298,9 @@ public fun NumberedPolynomial.substitute(ring: Ring, args: Map val acc = LinkedHashMap, C>(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, substitutor) -> + val newC = args.entries.fold(c) { product, (variable, substitution) -> val deg = degs.getOrElse(variable) { 0u } - if (deg == 0u) product else product * power(substitutor, deg) + if (deg == 0u) product else product * power(substitution, deg) } if (newDegs !in acc) acc[newDegs] = newC else acc[newDegs] = acc[newDegs]!! + newC @@ -315,9 +315,9 @@ public fun NumberedPolynomial.substitute(ring: Ring, args: Map, NumberedPolynomial>(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.asNumberedPolynomial()) { product, (variable, substitutor) -> + val newC = args.entries.fold(c.asNumberedPolynomial()) { product, (variable, substitution) -> val deg = degs.getOrElse(variable) { 0u } - if (deg == 0u) product else product * power(substitutor, deg) + if (deg == 0u) product else product * power(substitution, deg) } if (newDegs !in acc) acc[newDegs] = c.asNumberedPolynomial() else acc[newDegs] = acc[newDegs]!! + c diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt index e6d6b1ae6..a0c11b0a8 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt @@ -22,13 +22,13 @@ import kotlin.math.pow // if (degree > -1) Polynomial(coefficients.subList(0, degree + 1)) else zero /** - * Crates a [PolynomialSpace] over received ring. + * Creates a [PolynomialSpace] over a received ring. */ public fun > A.polynomial(): PolynomialSpace = PolynomialSpace(this) /** - * Crates a [PolynomialSpace]'s scope over received ring. + * Creates a [PolynomialSpace]'s scope over a received ring. */ public inline fun , R> A.polynomial(block: PolynomialSpace.() -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } @@ -36,13 +36,13 @@ public inline fun , R> A.polynomial(block: PolynomialSpace. } /** - * Crates a [ScalablePolynomialSpace] over received scalable ring. + * Creates a [ScalablePolynomialSpace] over a received scalable ring. */ public fun A.scalablePolynomial(): ScalablePolynomialSpace where A : Ring, A : ScaleOperations = ScalablePolynomialSpace(this) /** - * Crates a [ScalablePolynomialSpace]'s scope over received scalable ring. + * Creates a [ScalablePolynomialSpace]'s scope over a received scalable ring. */ public inline fun A.scalablePolynomial(block: ScalablePolynomialSpace.() -> R): R where A : Ring, A : ScaleOperations { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } -- 2.34.1 From e5186d469a68cf6284e7e1151cad184b33e25821 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Thu, 17 Mar 2022 02:12:40 +0300 Subject: [PATCH 037/275] Fixed issue with confusing `countOfVariables` in `Numbered...` --- .../kmath/functions/NumberedPolynomial.kt | 26 ++++++++++---- .../functions/NumberedRationalFunction.kt | 34 ++++++++++++++++--- 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index 307b78f29..37c0c96f0 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -432,12 +432,12 @@ public open class NumberedPolynomialSpace>( coefficients.all { (key, value) -> with(other.coefficients) { key in this && this[key] == value } } } - // TODO: Replace `countOfVariables` with `lastVariable` and create new `countOfVariables` /** - * Count of all variables that appear in the polynomial in positive exponents. + * 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.countOfVariables: Int - get() = coefficients.entries.maxOfOrNull { (degs, c) -> if (c.isZero()) 0 else degs.size } ?: 0 + public val NumberedPolynomial.lastVariable: Int + get() = coefficients.entries.maxOfOrNull { (degs, c) -> if (c.isZero()) -1 else 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. @@ -449,18 +449,30 @@ public open class NumberedPolynomialSpace>( * 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 size of the list is [countOfVariables]. + * And last index of the list is [lastVariable]. */ public val NumberedPolynomial.degrees: List get() = - buildList(countOfVariables) { - repeat(countOfVariables) { add(0U) } + MutableList(lastVariable + 1) { 0u }.apply { coefficients.entries.forEach { (degs, c) -> if (c.isNotZero()) degs.forEachIndexed { index, deg -> this[index] = max(this[index], deg) } } } + /** + * 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, c) -> + if (c.isNotZero()) degs.forEachIndexed { index, deg -> + if (deg != 0u) this[index] = true + } + } + }.count { it } /** * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt index 8e3b3b1c5..6542bc89b 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt @@ -277,12 +277,12 @@ public class NumberedRationalFunctionSpace> ( if ( !(numerator.isZero() xor other.numerator.isZero()) ) return false - val countOfVariables = max(this.countOfVariables, other.countOfVariables) + val countOfVariables = max(this.lastVariable, other.lastVariable) val thisNumeratorDegrees = this.numerator.degrees val thisDenominatorDegrees = this.denominator.degrees val otherNumeratorDegrees = other.numerator.degrees val otherDenominatorDegrees = other.denominator.degrees - for (variable in 0 until countOfVariables) + for (variable in 0 .. countOfVariables) if ( thisNumeratorDegrees.getOrElse(variable) { 0u } + otherDenominatorDegrees.getOrElse(variable) { 0u } != thisDenominatorDegrees.getOrElse(variable) { 0u } + otherNumeratorDegrees.getOrElse(variable) { 0u } @@ -292,9 +292,10 @@ public class NumberedRationalFunctionSpace> ( } /** - * Count of all variables that appear in the polynomial in positive exponents. + * 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.countOfVariables: Int get() = polynomialRing { countOfVariables } + 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. @@ -303,12 +304,35 @@ public class NumberedRationalFunctionSpace> ( * And size of the list is [countOfVariables]. */ public val NumberedPolynomial.degrees: List get() = polynomialRing { degrees } + /** + * 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() = polynomialRing { max(numerator.countOfVariables, denominator.countOfVariables) } + get() = + MutableList(lastVariable + 1) { false }.apply { + numerator.coefficients.entries.forEach { (degs, c) -> + if (c.isNotZero()) degs.forEachIndexed { index, deg -> + if (deg != 0u) this[index] = true + } + } + denominator.coefficients.entries.forEach { (degs, c) -> + if (c.isNotZero()) degs.forEachIndexed { index, deg -> + if (deg != 0u) this[index] = true + } + } + }.count { it } // TODO: Разобрать -- 2.34.1 From a8a95c9df7727f0a2b4bada88c122a912e8b1796 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Thu, 17 Mar 2022 02:15:48 +0300 Subject: [PATCH 038/275] Fixed typo --- .../space/kscience/kmath/functions/NumberedRationalFunction.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt index 6542bc89b..78ba233f5 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt @@ -301,7 +301,7 @@ public class NumberedRationalFunctionSpace> ( * 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 size of the list is [countOfVariables]. + * And last index of the list is [lastVariable]. */ public val NumberedPolynomial.degrees: List get() = polynomialRing { degrees } /** -- 2.34.1 From ffd3ae76844499ca9a6ac46ce23eaa7fc87f06e3 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Thu, 17 Mar 2022 16:02:41 +0300 Subject: [PATCH 039/275] Optimized allocation during coefficients generation in `Polynomial` --- .../kscience/kmath/functions/Polynomial.kt | 114 ++++++++++++------ 1 file changed, 79 insertions(+), 35 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 220bde8ff..862ee6a60 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -6,6 +6,10 @@ package space.kscience.kmath.functions import space.kscience.kmath.operations.* +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract +import kotlin.experimental.ExperimentalTypeInference +import kotlin.jvm.JvmName import kotlin.math.max import kotlin.math.min @@ -124,8 +128,9 @@ public open class PolynomialSpace>( if (other == 0) zero else Polynomial( coefficients - .subList(0, degree + 1) - .map { it * other } + .applyAndRemoveZeros { + map { it * other } + } ) /** @@ -183,8 +188,9 @@ public open class PolynomialSpace>( if (this == 0) zero else Polynomial( other.coefficients - .subList(0, other.degree + 1) - .map { it * this } + .applyAndRemoveZeros { + map { it * this@times } + } ) /** @@ -238,8 +244,9 @@ public open class PolynomialSpace>( if (this.isZero()) other else Polynomial( other.coefficients - .subList(0, other.degree + 1) - .map { it * this } + .applyAndRemoveZeros { + map { it * this@times } + } ) /** @@ -291,8 +298,9 @@ public open class PolynomialSpace>( if (other.isZero()) this else Polynomial( coefficients - .subList(0, degree + 1) - .map { it * other } + .applyAndRemoveZeros { + map { it * other } + } ) /** @@ -303,33 +311,35 @@ public open class PolynomialSpace>( /** * Returns sum of the polynomials. */ - public override operator fun Polynomial.plus(other: Polynomial): Polynomial = - Polynomial( - (0..max(degree, other.degree)) - .map { - when { - it > degree -> other.coefficients[it] - it > other.degree -> coefficients[it] - else -> coefficients[it] + other.coefficients[it] - } + public override operator fun Polynomial.plus(other: Polynomial): Polynomial { + val thisDegree = degree + val otherDegree = other.degree + return Polynomial( + Coefficients(max(thisDegree, otherDegree) + 1) { + when { + it > thisDegree -> other.coefficients[it] + it > otherDegree -> coefficients[it] + else -> coefficients[it] + other.coefficients[it] } - .ifEmpty { listOf(constantZero) } + } ) + } /** * Returns difference of the polynomials. */ - public override operator fun Polynomial.minus(other: Polynomial): Polynomial = - Polynomial( - (0..max(degree, other.degree)) - .map { - when { - it > degree -> -other.coefficients[it] - it > other.degree -> coefficients[it] - else -> coefficients[it] - other.coefficients[it] - } + public override operator fun Polynomial.minus(other: Polynomial): Polynomial { + val thisDegree = degree + val otherDegree = other.degree + return Polynomial( + Coefficients(max(thisDegree, otherDegree) + 1) { + when { + it > thisDegree -> -other.coefficients[it] + it > otherDegree -> coefficients[it] + else -> coefficients[it] - other.coefficients[it] } - .ifEmpty { listOf(constantZero) } + } ) + } /** * Returns product of the polynomials. */ @@ -341,13 +351,11 @@ public open class PolynomialSpace>( otherDegree == -1 -> zero else -> Polynomial( - (0..(thisDegree + otherDegree)) - .map { d -> - (max(0, d - otherDegree)..min(thisDegree, d)) - .map { coefficients[it] * other.coefficients[d - it] } - .reduce { acc, rational -> acc + rational } - } - .run { subList(0, indexOfLast { it.isNotZero() } + 1) } + Coefficients(thisDegree + otherDegree + 1) { d -> + (max(0, d - otherDegree)..min(thisDegree, d)) + .map { coefficients[it] * other.coefficients[d - it] } + .reduce { acc, rational -> acc + rational } + } ) } } @@ -431,6 +439,42 @@ public open class PolynomialSpace>( public inline operator fun Polynomial.invoke(argument: C): C = this.substitute(ring, argument) @Suppress("NOTHING_TO_INLINE") public inline operator fun Polynomial.invoke(argument: Polynomial): Polynomial = this.substitute(ring, argument) + + // TODO: Move to other internal utilities with context receiver + @JvmName("applyAndRemoveZerosInternal") + internal inline fun MutableList.applyAndRemoveZeros(block: MutableList.() -> Unit) : MutableList { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + block() + while (elementAt(lastIndex).isZero()) removeAt(lastIndex) + return this + } + internal inline fun List.applyAndRemoveZeros(block: MutableList.() -> Unit) : List = + toMutableList().applyAndRemoveZeros(block) + internal inline fun MutableCoefficients(size: Int, init: (index: Int) -> C): MutableList { + val list = ArrayList(size) + repeat(size) { index -> list.add(init(index)) } + with(list) { while (elementAt(lastIndex).isZero()) removeAt(lastIndex) } + return list + } + internal inline fun Coefficients(size: Int, init: (index: Int) -> C): List = MutableCoefficients(size, init) + @OptIn(ExperimentalTypeInference::class) + internal inline fun buildCoefficients(@BuilderInference builderAction: MutableList.() -> Unit): List { + contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } + return buildList { + builderAction() + while (elementAt(lastIndex).isZero()) removeAt(lastIndex) + } + } + @OptIn(ExperimentalTypeInference::class) + internal inline fun buildCoefficients(capacity: Int, @BuilderInference builderAction: MutableList.() -> Unit): List { + contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } + return buildList(capacity) { + builderAction() + while (elementAt(lastIndex).isZero()) removeAt(lastIndex) + } + } } /** -- 2.34.1 From d63c4acf101849c0bbe2242d841bf7faaf6047e3 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Thu, 17 Mar 2022 16:27:02 +0300 Subject: [PATCH 040/275] Added space and scope fabrics for RFs --- .../functions/labeledRationalFunctionUtil.kt | 18 ++++++++++++++++++ .../functions/numberedRationalFunctionUtil.kt | 18 ++++++++++++++++++ .../kmath/functions/rationalFunctionUtil.kt | 18 ++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt index 61f443871..d79e8eda3 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt @@ -5,6 +5,24 @@ package space.kscience.kmath.functions +import space.kscience.kmath.operations.Ring +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract + + +/** + * Creates a [LabeledRationalFunctionSpace] over a received ring. + */ +public fun > A.labeledRationalFunction(): LabeledRationalFunctionSpace = + LabeledRationalFunctionSpace(this) + +/** + * Creates a [RationalFunctionSpace]'s scope over a received ring. + */ +public inline fun , R> A.labeledRationalFunction(block: LabeledRationalFunctionSpace.() -> R): R { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return LabeledRationalFunctionSpace(this).block() +} //fun > LabeledRationalFunction.reduced(): LabeledRationalFunction { // val greatestCommonDivider = polynomialGCD(numerator, denominator) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt index 035e201f7..cc725f981 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt @@ -5,6 +5,24 @@ package space.kscience.kmath.functions +import space.kscience.kmath.operations.Ring +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract + + +/** + * Creates a [NumberedRationalFunctionSpace] over a received ring. + */ +public fun > A.numberedRationalFunction(): NumberedRationalFunctionSpace = + NumberedRationalFunctionSpace(this) + +/** + * Creates a [RationalFunctionSpace]'s scope over a received ring. + */ +public inline fun , R> A.numberedRationalFunction(block: NumberedRationalFunctionSpace.() -> R): R { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return NumberedRationalFunctionSpace(this).block() +} //fun > NumberedRationalFunction.reduced(): NumberedRationalFunction { // val greatestCommonDivider = polynomialGCD(numerator, denominator) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/rationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/rationalFunctionUtil.kt index 359c781b5..456a1fa2b 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/rationalFunctionUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/rationalFunctionUtil.kt @@ -5,6 +5,24 @@ package space.kscience.kmath.functions +import space.kscience.kmath.operations.Ring +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract + + +/** + * Creates a [RationalFunctionSpace] over a received ring. + */ +public fun > A.rationalFunction(): RationalFunctionSpace = + RationalFunctionSpace(this) + +/** + * Creates a [RationalFunctionSpace]'s scope over a received ring. + */ +public inline fun , R> A.rationalFunction(block: RationalFunctionSpace.() -> R): R { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return RationalFunctionSpace(this).block() +} //operator fun > RationalFunction.invoke(arg: T): T = numerator(arg) / denominator(arg) // -- 2.34.1 From 86553e9f35aa5891b89bdcd187ff348dcc9955fb Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Thu, 17 Mar 2022 16:28:41 +0300 Subject: [PATCH 041/275] Added utilities. Rewrote polynomial-in-polynomial substitution --- .../kmath/functions/polynomialUtil.kt | 55 ++++++++++++++++--- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt index a0c11b0a8..c624380be 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt @@ -49,6 +49,41 @@ public inline fun A.scalablePolynomial(block: ScalablePolynomialSpace< return ScalablePolynomialSpace(this).block() } +@Suppress("NOTHING_TO_INLINE") +internal inline fun iadd( + ring: Ring, + augend: MutableList, + addend: List, + degree: Int +) = ring { + for (deg in 0 .. degree) augend[deg] += addend[deg] +} + +@Suppress("NOTHING_TO_INLINE") +internal inline fun addTo( + ring: Ring, + augend: List, + addend: List, + degree: Int, + target: MutableList +) = ring { + for (deg in 0 .. degree) target[deg] = augend[deg] + addend[deg] +} + +@Suppress("NOTHING_TO_INLINE") +internal inline fun multiplyAddingTo( + ring: Ring, + multiplicand: List, + multiplicandDegree: Int, + multiplier: List, + multiplierDegree: Int, + target: MutableList +) = ring { + for (d in 0 .. multiplicandDegree + multiplierDegree) + for (k in max(0, d - multiplierDegree)..min(multiplicandDegree, d)) + target[d] += multiplicand[k] * multiplier[d - k] +} + // TODO: May be apply Horner's method too? /** * Evaluates the value of the given double polynomial for given double argument. @@ -80,19 +115,21 @@ public fun Polynomial.substitute(ring: Ring, arg: Polynomial) : Pol val argDegree = arg.degree if (argDegree == -1) return coefficients[0].asPolynomial() val constantZero = constantZero - val resultCoefs: MutableList = MutableList(thisDegree + argDegree + 1) { constantZero } - val resultCoefsUpdate: MutableList = MutableList(thisDegree + argDegree + 1) { constantZero } + val resultCoefs: MutableList = MutableList(thisDegree * argDegree + 1) { constantZero } + val resultCoefsUpdate: MutableList = MutableList(thisDegree * argDegree + 1) { constantZero } var resultDegree = 0 for (deg in thisDegree downTo 0) { resultCoefsUpdate[0] = coefficients[deg] - for (updateDeg in 0 .. resultDegree + argDegree) { - var newC = resultCoefsUpdate[updateDeg] - for (deg1 in max(0, updateDeg - argDegree)..min(resultDegree, updateDeg)) - newC += resultCoefs[deg1] * arg.coefficients[updateDeg - deg1] - resultCoefsUpdate[updateDeg] = newC - } + multiplyAddingTo( + ring=ring, + multiplicand = resultCoefs, + multiplicandDegree = resultDegree, + multiplier = arg.coefficients, + multiplierDegree = argDegree, + target = resultCoefsUpdate + ) resultDegree += argDegree - for (updateDeg in 0 .. resultDegree + argDegree) { + for (updateDeg in 0 .. resultDegree) { resultCoefs[updateDeg] = resultCoefsUpdate[updateDeg] resultCoefsUpdate[updateDeg] = constantZero } -- 2.34.1 From ed2f14b68e7f799fcbe370bf744256a278cfcf74 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Fri, 18 Mar 2022 01:47:03 +0300 Subject: [PATCH 042/275] Optimised existing substitution function. Prototyped substitution for RFs. --- .../kmath/functions/polynomialUtil.kt | 63 ++++--- .../kmath/functions/rationalFunctionUtil.kt | 174 ++++++++++++++++++ 2 files changed, 210 insertions(+), 27 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt index c624380be..1a7245b9f 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt @@ -50,24 +50,36 @@ public inline fun A.scalablePolynomial(block: ScalablePolynomialSpace< } @Suppress("NOTHING_TO_INLINE") -internal inline fun iadd( - ring: Ring, - augend: MutableList, - addend: List, - degree: Int -) = ring { - for (deg in 0 .. degree) augend[deg] += addend[deg] +internal inline fun copyTo( + origin: List, + originDegree: Int, + target: MutableList, +) { + for (deg in 0 .. originDegree) target[deg] = origin[deg] } @Suppress("NOTHING_TO_INLINE") -internal inline fun addTo( +internal inline fun multiplyAddingToUpdater( ring: Ring, - augend: List, - addend: List, - degree: Int, - target: MutableList -) = ring { - for (deg in 0 .. degree) target[deg] = augend[deg] + addend[deg] + multiplicand: MutableList, + multiplicandDegree: Int, + multiplier: List, + multiplierDegree: Int, + updater: MutableList, + zero: C, +) { + multiplyAddingTo( + ring = ring, + multiplicand = multiplicand, + multiplicandDegree = multiplicandDegree, + multiplier = multiplier, + multiplierDegree = multiplierDegree, + target = updater + ) + for (updateDeg in 0 .. multiplicandDegree + multiplierDegree) { + multiplicand[updateDeg] = updater[updateDeg] + updater[updateDeg] = zero + } } @Suppress("NOTHING_TO_INLINE") @@ -107,32 +119,29 @@ public fun Polynomial.substitute(ring: Ring, arg: C): C = ring { return result } -public fun Polynomial.substitute(ring: Ring, arg: Polynomial) : Polynomial = ring.polynomial { - if (coefficients.isEmpty()) return zero +public fun Polynomial.substitute(ring: Ring, arg: Polynomial) : Polynomial = ring { + if (coefficients.isEmpty()) return Polynomial(emptyList()) - val thisDegree = degree - if (thisDegree == -1) return zero - val argDegree = arg.degree + val thisDegree = coefficients.indexOfLast { it != zero } + if (thisDegree == -1) return Polynomial(emptyList()) + val argDegree = arg.coefficients.indexOfLast { it != zero } if (argDegree == -1) return coefficients[0].asPolynomial() - val constantZero = constantZero + val constantZero = zero val resultCoefs: MutableList = MutableList(thisDegree * argDegree + 1) { constantZero } val resultCoefsUpdate: MutableList = MutableList(thisDegree * argDegree + 1) { constantZero } var resultDegree = 0 for (deg in thisDegree downTo 0) { resultCoefsUpdate[0] = coefficients[deg] - multiplyAddingTo( - ring=ring, + multiplyAddingToUpdater( + ring = ring, multiplicand = resultCoefs, multiplicandDegree = resultDegree, multiplier = arg.coefficients, multiplierDegree = argDegree, - target = resultCoefsUpdate + updater = resultCoefsUpdate, + zero = constantZero ) resultDegree += argDegree - for (updateDeg in 0 .. resultDegree) { - resultCoefs[updateDeg] = resultCoefsUpdate[updateDeg] - resultCoefsUpdate[updateDeg] = constantZero - } } return Polynomial(resultCoefs) } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/rationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/rationalFunctionUtil.kt index 456a1fa2b..8d2073834 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/rationalFunctionUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/rationalFunctionUtil.kt @@ -5,9 +5,12 @@ package space.kscience.kmath.functions +import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.invoke import kotlin.contracts.InvocationKind import kotlin.contracts.contract +import kotlin.math.max /** @@ -24,6 +27,177 @@ public inline fun , R> A.rationalFunction(block: RationalFunction return RationalFunctionSpace(this).block() } +/** + * Evaluates the value of the given double polynomial for given double argument. + */ +public fun RationalFunction.substitute(arg: Double): Double = + numerator.substitute(arg) / denominator.substitute(arg) + +/** + * Evaluates the value of the given polynomial for given argument. + * + * It is an implementation of [Horner's method](https://en.wikipedia.org/wiki/Horner%27s_method). + */ +public fun RationalFunction.substitute(ring: Field, arg: C): C = ring { + numerator.substitute(ring, arg) / denominator.substitute(ring, arg) +} + +/** + * Returns numerator (polynomial) of rational function gotten by substitution rational function [arg] to the polynomial instance. + * More concrete, if [arg] is a fraction `f(x)/g(x)` and the receiving instance is `p(x)`, then + * ``` + * p(f/g) * g^deg(p) + * ``` + * is returned. + * + * Used in [Polynomial.substitute] and [RationalFunction.substitute] for performance optimisation. + */ // TODO: Дописать +internal fun Polynomial.substituteRationalFunctionTakeNumerator(ring: Ring, arg: RationalFunction): Polynomial = ring { + if (coefficients.isEmpty()) return Polynomial(emptyList()) + + val thisDegree = coefficients.indexOfLast { it != zero } + if (thisDegree == -1) return Polynomial(emptyList()) + val thisDegreeLog2 = 31 - thisDegree.countLeadingZeroBits() + val numeratorDegree = arg.numerator.coefficients.indexOfLast { it != zero } + val denominatorDegree = arg.denominator.coefficients.indexOfLast { it != zero } + val argDegree = max(numeratorDegree, denominatorDegree) + val constantZero = zero + val powersOf2 = buildList(thisDegreeLog2 + 1) { + var result = 1 + for (exp in 0 .. thisDegreeLog2) { + add(result) + result = result shl 1 + } + } + val hashes = powersOf2.runningReduce { acc, i -> acc + i } + val numeratorPowers = buildList>(thisDegreeLog2 + 1) { + add(arg.numerator.coefficients) + repeat(thisDegreeLog2) { + val next = MutableList(powersOf2[it + 1] * numeratorDegree + 1) { constantZero } + add(next) + val last = last() + multiplyAddingTo( + ring = ring, + multiplicand = last, + multiplicandDegree = powersOf2[it] * numeratorDegree + 1, + multiplier = last, + multiplierDegree = powersOf2[it] * numeratorDegree + 1, + target = next, + ) + } + } + val denominatorPowers = buildList>(thisDegreeLog2 + 1) { + add(arg.denominator.coefficients) + repeat(thisDegreeLog2) { + val next = MutableList(powersOf2[it + 1] * denominatorDegree + 1) { constantZero } + add(next) + val last = last() + multiplyAddingTo( + ring = ring, + multiplicand = last, + multiplicandDegree = powersOf2[it] * denominatorDegree + 1, + multiplier = last, + multiplierDegree = powersOf2[it] * denominatorDegree + 1, + target = next, + ) + } + } + val levelResultCoefsPool = buildList>(thisDegreeLog2 + 1) { + repeat(thisDegreeLog2 + 1) { + add(MutableList(hashes[it] * argDegree) { constantZero }) + } + } + val edgedMultiplier = MutableList(0) { TODO() } + val edgedMultiplierUpdater = MutableList(0) { TODO() } + + fun MutableList.reset() { + for (i in indices) set(i, constantZero) + } + + fun processLevel(level: Int, start: Int, end: Int) : List { + val levelResultCoefs = levelResultCoefsPool[level + 1] + + if (level == -1) { + levelResultCoefs[0] = coefficients[start] + } else { + levelResultCoefs.reset() + multiplyAddingTo( + ring = ring, + multiplicand = processLevel(level = level - 1, start = start, end = (start + end) / 2), + multiplicandDegree = hashes[level] * argDegree, + multiplier = denominatorPowers[level], + multiplierDegree = powersOf2[level] * denominatorDegree, + target = levelResultCoefs + ) + multiplyAddingTo( + ring = ring, + multiplicand = processLevel(level = level - 1, start = (start + end) / 2, end = end), + multiplicandDegree = hashes[level] * argDegree, + multiplier = numeratorPowers[level], + multiplierDegree = powersOf2[level] * numeratorDegree, + target = levelResultCoefs + ) + } + + return levelResultCoefs + } + + fun processLevelEdged(level: Int, start: Int, end: Int) : List { + val levelResultCoefs = levelResultCoefsPool[level + 1] + + if (level == -1) { + levelResultCoefs[0] = coefficients[start] + } else { + val levelsPowerOf2 = powersOf2[level] + if (end - start >= levelsPowerOf2) { + multiplyAddingTo( + ring = ring, + multiplicand = processLevelEdged(level = level - 1, start = start + levelsPowerOf2, end = end), + multiplicandDegree = hashes[level] * argDegree, // TODO: Ввести переменную + multiplier = numeratorPowers[level], + multiplierDegree = powersOf2[level] * numeratorDegree, + target = levelResultCoefs + ) + multiplyAddingTo( + ring = ring, + multiplicand = processLevel(level = level - 1, start = start, end = start + levelsPowerOf2), + multiplicandDegree = hashes[level] * argDegree, + multiplier = edgedMultiplier, + multiplierDegree = max((hashes[level] and thisDegree) - powersOf2[level] + 1, 0) * denominatorDegree, // TODO: Ввести переменную + target = levelResultCoefs + ) + if (level != thisDegreeLog2) { + multiplyAddingToUpdater( + ring = ring, + multiplicand = edgedMultiplier, + multiplicandDegree = max((hashes[level] and thisDegree) - powersOf2[level] + 1, 0) * denominatorDegree, // TODO: Ввести переменную + multiplier = denominatorPowers[level], + multiplierDegree = powersOf2[level] * denominatorDegree, + updater = edgedMultiplierUpdater, + zero = constantZero + ) + } + } else { + copyTo( + origin = processLevelEdged(level = level - 1, start = start + levelsPowerOf2, end = end), + originDegree = hashes[level] * argDegree, // TODO: Ввести переменную + target = levelResultCoefs + ) + } + } + + return levelResultCoefs + } + + return Polynomial( + processLevelEdged( + level = thisDegreeLog2, + start = 0, + end = thisDegree + 1 + ) + ) +} + //operator fun > RationalFunction.invoke(arg: T): T = numerator(arg) / denominator(arg) // //fun > RationalFunction.reduced(): RationalFunction = -- 2.34.1 From cdc85291bc5d5c9313e25c5d11649415155087d0 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Fri, 18 Mar 2022 20:04:21 +0300 Subject: [PATCH 043/275] Fixed bug in implementations of polynomial operations --- .../kmath/functions/LabeledPolynomial.kt | 26 +++++++++---------- .../kmath/functions/NumberedPolynomial.kt | 26 +++++++++---------- .../kscience/kmath/functions/Polynomial.kt | 10 ++++--- .../kmath/functions/polynomialUtil.kt | 1 - 4 files changed, 30 insertions(+), 33 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt index 369c7078a..76f5fc29c 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -211,7 +211,7 @@ public class LabeledPolynomialSpace>( else LabeledPolynomial( coefficients .applyAndRemoveZeros { - mapValues { (_, c) -> c * other } + for (degs in keys) this[degs] = this[degs]!! * other } ) @@ -265,7 +265,7 @@ public class LabeledPolynomialSpace>( else LabeledPolynomial( other.coefficients .applyAndRemoveZeros { - mapValues { (_, c) -> this@times * c } + for (degs in keys) this[degs] = this@times * this[degs]!! } ) @@ -361,7 +361,7 @@ public class LabeledPolynomialSpace>( else LabeledPolynomial( other.coefficients .applyAndRemoveZeros { - mapValues { (_, c) -> this@times * c } + for (degs in keys) this[degs] = this@times * this[degs]!! } ) @@ -413,7 +413,7 @@ public class LabeledPolynomialSpace>( else LabeledPolynomial( coefficients .applyAndRemoveZeros { - mapValues { (_, c) -> c * other } + for (degs in keys) this[degs] = this[degs]!! * other } ) @@ -525,22 +525,20 @@ public class LabeledPolynomialSpace>( */ override operator fun LabeledPolynomial.plus(other: LabeledPolynomial): LabeledPolynomial = LabeledPolynomial( - coefficients - .applyAndRemoveZeros { - other.coefficients - .mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value } - } + buildCoefficients(coefficients.size + other.coefficients.size) { + other.coefficients.mapValuesTo(this) { it.value } + other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value } + } ) /** * Returns difference of the polynomials. */ override operator fun LabeledPolynomial.minus(other: LabeledPolynomial): LabeledPolynomial = LabeledPolynomial( - coefficients - .applyAndRemoveZeros { - other.coefficients - .mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value } - } + buildCoefficients(coefficients.size + other.coefficients.size) { + other.coefficients.mapValuesTo(this) { it.value } + other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value } + } ) /** * Returns product of the polynomials. diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index 37c0c96f0..88349f003 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -163,7 +163,7 @@ public open class NumberedPolynomialSpace>( else NumberedPolynomial( coefficients .applyAndRemoveZeros { - mapValues { (_, c) -> c * other } + for (degs in keys) this[degs] = this[degs]!! * other } ) @@ -217,7 +217,7 @@ public open class NumberedPolynomialSpace>( else NumberedPolynomial( other.coefficients .applyAndRemoveZeros { - mapValues { (_, c) -> this@times * c } + for (degs in keys) this[degs] = this@times * this[degs]!! } ) @@ -269,7 +269,7 @@ public open class NumberedPolynomialSpace>( else NumberedPolynomial( other.coefficients .applyAndRemoveZeros { - mapValues { (_, c) -> this@times * c } + for (degs in keys) this[degs] = this@times * this[degs]!! } ) @@ -319,7 +319,7 @@ public open class NumberedPolynomialSpace>( else NumberedPolynomial( coefficients .applyAndRemoveZeros { - mapValues { (_, c) -> c * other } + for (degs in keys) this[degs] = this[degs]!! * other } ) @@ -335,22 +335,20 @@ public open class NumberedPolynomialSpace>( */ override operator fun NumberedPolynomial.plus(other: NumberedPolynomial): NumberedPolynomial = NumberedPolynomial( - coefficients - .applyAndRemoveZeros { - other.coefficients - .mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value } - } + buildCoefficients(coefficients.size + other.coefficients.size) { + other.coefficients.mapValuesTo(this) { it.value } + other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value } + } ) /** * Returns difference of the polynomials. */ override operator fun NumberedPolynomial.minus(other: NumberedPolynomial): NumberedPolynomial = NumberedPolynomial( - coefficients - .applyAndRemoveZeros { - other.coefficients - .mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value } - } + buildCoefficients(coefficients.size + other.coefficients.size) { + other.coefficients.mapValuesTo(this) { it.value } + other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value } + } ) /** * Returns product of the polynomials. diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 862ee6a60..a60ca563a 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -129,7 +129,7 @@ public open class PolynomialSpace>( else Polynomial( coefficients .applyAndRemoveZeros { - map { it * other } + for (deg in indices) this[deg] = this[deg] * other } ) @@ -189,7 +189,7 @@ public open class PolynomialSpace>( else Polynomial( other.coefficients .applyAndRemoveZeros { - map { it * this@times } + for (deg in indices) this[deg] = this@times * this[deg] } ) @@ -245,7 +245,7 @@ public open class PolynomialSpace>( else Polynomial( other.coefficients .applyAndRemoveZeros { - map { it * this@times } + for (deg in indices) this[deg] = this@times * this[deg] } ) @@ -299,7 +299,7 @@ public open class PolynomialSpace>( else Polynomial( coefficients .applyAndRemoveZeros { - map { it * other } + for (deg in indices) this[deg] = this[deg] * other } ) @@ -452,12 +452,14 @@ public open class PolynomialSpace>( } internal inline fun List.applyAndRemoveZeros(block: MutableList.() -> Unit) : List = toMutableList().applyAndRemoveZeros(block) + @Suppress("FunctionName") internal inline fun MutableCoefficients(size: Int, init: (index: Int) -> C): MutableList { val list = ArrayList(size) repeat(size) { index -> list.add(init(index)) } with(list) { while (elementAt(lastIndex).isZero()) removeAt(lastIndex) } return list } + @Suppress("FunctionName") internal inline fun Coefficients(size: Int, init: (index: Int) -> C): List = MutableCoefficients(size, init) @OptIn(ExperimentalTypeInference::class) internal inline fun buildCoefficients(@BuilderInference builderAction: MutableList.() -> Unit): List { diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt index 1a7245b9f..84c8d2e88 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt @@ -96,7 +96,6 @@ internal inline fun multiplyAddingTo( target[d] += multiplicand[k] * multiplier[d - k] } -// TODO: May be apply Horner's method too? /** * Evaluates the value of the given double polynomial for given double argument. */ -- 2.34.1 From 85cd3b4de64b35718d603033dba4aec97879578d Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Fri, 18 Mar 2022 20:39:01 +0300 Subject: [PATCH 044/275] Added some test. Fixed bug in algebraicStub.kt --- .../kscience/kmath/functions/algebraicStub.kt | 2 +- .../kmath/functions/AlgebraicStubTest.kt | 589 ++++++++++++++++++ .../kmath/functions/PolynomialTest.kt | 5 +- 3 files changed, 593 insertions(+), 3 deletions(-) create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt index ee81f3d79..ca93e4259 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt @@ -139,7 +139,7 @@ internal tailrec fun Ring.exponentiationBySquaring(arg: C, exponent: UInt internal tailrec fun RingOps.multiplyExponentiationBySquaring(base: C, arg: C, exponent: UInt): C = when { exponent == 0u -> base - exponent == 1u -> base + arg + exponent == 1u -> base * arg exponent and 1u == 0u -> multiplyExponentiationBySquaring(base, arg * arg, exponent shr 1) exponent and 1u == 1u -> multiplyExponentiationBySquaring(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") diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt new file mode 100644 index 000000000..fe4a82f11 --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt @@ -0,0 +1,589 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.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", + addMultipliedBySquaring(Expr("57"), Expr("179"), 0u).expr, + "tried addMultipliedBySquaring(57, 179, 0u)" + ) + assertEquals( + "(57 + 179)", + addMultipliedBySquaring(Expr("57"), Expr("179"), 1u).expr, + "tried addMultipliedBySquaring(57, 179, 1u)" + ) + assertEquals( + "(57 + (179 + 179))", + addMultipliedBySquaring(Expr("57"), Expr("179"), 2u).expr, + "tried addMultipliedBySquaring(57, 179, 2u)" + ) + assertEquals( + "((57 + 179) + (179 + 179))", + addMultipliedBySquaring(Expr("57"), Expr("179"), 3u).expr, + "tried addMultipliedBySquaring(57, 179, 3u)" + ) + assertEquals( + "(57 + ((179 + 179) + (179 + 179)))", + addMultipliedBySquaring(Expr("57"), Expr("179"), 4u).expr, + "tried addMultipliedBySquaring(57, 179, 4u)" + ) + assertEquals( + "((57 + 179) + ((179 + 179) + (179 + 179)))", + addMultipliedBySquaring(Expr("57"), Expr("179"), 5u).expr, + "tried addMultipliedBySquaring(57, 179, 5u)" + ) + assertEquals( + "((57 + (179 + 179)) + ((179 + 179) + (179 + 179)))", + addMultipliedBySquaring(Expr("57"), Expr("179"), 6u).expr, + "tried addMultipliedBySquaring(57, 179, 6u)" + ) + assertEquals( + "(((57 + 179) + (179 + 179)) + ((179 + 179) + (179 + 179)))", + addMultipliedBySquaring(Expr("57"), Expr("179"), 7u).expr, + "tried addMultipliedBySquaring(57, 179, 7u)" + ) + assertEquals( + "(57 + (((179 + 179) + (179 + 179)) + ((179 + 179) + (179 + 179))))", + addMultipliedBySquaring(Expr("57"), Expr("179"), 8u).expr, + "tried addMultipliedBySquaring(57, 179, 8u)" + ) + } + } + @Test + fun test_multiplyBySquaring_for_UInt() { + ExprRing { + assertEquals( + "0", + multiplyBySquaring(Expr("57"), 0u).expr, + "tried multiplyBySquaring(57, 0u)" + ) + assertEquals( + "57", + multiplyBySquaring(Expr("57"), 1u).expr, + "tried multiplyBySquaring(57, 1u)" + ) + assertEquals( + "(57 + 57)", + multiplyBySquaring(Expr("57"), 2u).expr, + "tried multiplyBySquaring(57, 2u)" + ) + assertEquals( + "(57 + (57 + 57))", + multiplyBySquaring(Expr("57"), 3u).expr, + "tried multiplyBySquaring(57, 3u)" + ) + assertEquals( + "((57 + 57) + (57 + 57))", + multiplyBySquaring(Expr("57"), 4u).expr, + "tried multiplyBySquaring(57, 4u)" + ) + assertEquals( + "(57 + ((57 + 57) + (57 + 57)))", + multiplyBySquaring(Expr("57"), 5u).expr, + "tried multiplyBySquaring(57, 5u)" + ) + assertEquals( + "((57 + 57) + ((57 + 57) + (57 + 57)))", + multiplyBySquaring(Expr("57"), 6u).expr, + "tried multiplyBySquaring(57, 6u)" + ) + assertEquals( + "((57 + (57 + 57)) + ((57 + 57) + (57 + 57)))", + multiplyBySquaring(Expr("57"), 7u).expr, + "tried multiplyBySquaring(57, 7u)" + ) + assertEquals( + "(((57 + 57) + (57 + 57)) + ((57 + 57) + (57 + 57)))", + multiplyBySquaring(Expr("57"), 8u).expr, + "tried multiplyBySquaring(57, 8u)" + ) + } + } + @Test + fun test_addMultipliedBySquaring_for_Int() { + ExprRing { + assertEquals( + "57", + addMultipliedBySquaring(Expr("57"), Expr("179"), 0).expr, + "tried addMultipliedBySquaring(57, 179, 0)" + ) + assertEquals( + "(57 + 179)", + addMultipliedBySquaring(Expr("57"), Expr("179"), 1).expr, + "tried addMultipliedBySquaring(57, 179, 1)" + ) + assertEquals( + "(57 + -179)", + addMultipliedBySquaring(Expr("57"), Expr("179"), -1).expr, + "tried addMultipliedBySquaring(57, 179, -1)" + ) + assertEquals( + "(57 + (179 + 179))", + addMultipliedBySquaring(Expr("57"), Expr("179"), 2).expr, + "tried addMultipliedBySquaring(57, 179, 2)" + ) + assertEquals( + "(57 + (-179 + -179))", + addMultipliedBySquaring(Expr("57"), Expr("179"), -2).expr, + "tried addMultipliedBySquaring(57, 179, -2)" + ) + assertEquals( + "((57 + 179) + (179 + 179))", + addMultipliedBySquaring(Expr("57"), Expr("179"), 3).expr, + "tried addMultipliedBySquaring(57, 179, 3)" + ) + assertEquals( + "((57 + -179) + (-179 + -179))", + addMultipliedBySquaring(Expr("57"), Expr("179"), -3).expr, + "tried addMultipliedBySquaring(57, 179, -3)" + ) + assertEquals( + "(57 + ((179 + 179) + (179 + 179)))", + addMultipliedBySquaring(Expr("57"), Expr("179"), 4).expr, + "tried addMultipliedBySquaring(57, 179, 4)" + ) + assertEquals( + "(57 + ((-179 + -179) + (-179 + -179)))", + addMultipliedBySquaring(Expr("57"), Expr("179"), -4).expr, + "tried addMultipliedBySquaring(57, 179, -4)" + ) + assertEquals( + "((57 + 179) + ((179 + 179) + (179 + 179)))", + addMultipliedBySquaring(Expr("57"), Expr("179"), 5).expr, + "tried addMultipliedBySquaring(57, 179, 5)" + ) + assertEquals( + "((57 + -179) + ((-179 + -179) + (-179 + -179)))", + addMultipliedBySquaring(Expr("57"), Expr("179"), -5).expr, + "tried addMultipliedBySquaring(57, 179, -5)" + ) + assertEquals( + "((57 + (179 + 179)) + ((179 + 179) + (179 + 179)))", + addMultipliedBySquaring(Expr("57"), Expr("179"), 6).expr, + "tried addMultipliedBySquaring(57, 179, 6)" + ) + assertEquals( + "((57 + (-179 + -179)) + ((-179 + -179) + (-179 + -179)))", + addMultipliedBySquaring(Expr("57"), Expr("179"), -6).expr, + "tried addMultipliedBySquaring(57, 179, -6)" + ) + assertEquals( + "(((57 + 179) + (179 + 179)) + ((179 + 179) + (179 + 179)))", + addMultipliedBySquaring(Expr("57"), Expr("179"), 7).expr, + "tried addMultipliedBySquaring(57, 179, 7)" + ) + assertEquals( + "(((57 + -179) + (-179 + -179)) + ((-179 + -179) + (-179 + -179)))", + addMultipliedBySquaring(Expr("57"), Expr("179"), -7).expr, + "tried addMultipliedBySquaring(57, 179, -7)" + ) + assertEquals( + "(57 + (((179 + 179) + (179 + 179)) + ((179 + 179) + (179 + 179))))", + addMultipliedBySquaring(Expr("57"), Expr("179"), 8).expr, + "tried addMultipliedBySquaring(57, 179, 8)" + ) + assertEquals( + "(57 + (((-179 + -179) + (-179 + -179)) + ((-179 + -179) + (-179 + -179))))", + addMultipliedBySquaring(Expr("57"), Expr("179"), -8).expr, + "tried addMultipliedBySquaring(57, 179, -8)" + ) + } + } + @Test + fun test_multiplyBySquaring_for_Int() { + ExprRing { + assertEquals( + "0", + multiplyBySquaring(Expr("57"), 0).expr, + "tried multiplyBySquaring(57, 0)" + ) + assertEquals( + "57", + multiplyBySquaring(Expr("57"), 1).expr, + "tried multiplyBySquaring(57, 1)" + ) + assertEquals( + "-57", + multiplyBySquaring(Expr("57"), -1).expr, + "tried multiplyBySquaring(57, -1)" + ) + assertEquals( + "(57 + 57)", + multiplyBySquaring(Expr("57"), 2).expr, + "tried multiplyBySquaring(57, 2)" + ) + assertEquals( + "(-57 + -57)", + multiplyBySquaring(Expr("57"), -2).expr, + "tried multiplyBySquaring(57, -2)" + ) + assertEquals( + "(57 + (57 + 57))", + multiplyBySquaring(Expr("57"), 3).expr, + "tried multiplyBySquaring(57, 3)" + ) + assertEquals( + "(-57 + (-57 + -57))", + multiplyBySquaring(Expr("57"), -3).expr, + "tried multiplyBySquaring(57, -3)" + ) + assertEquals( + "((57 + 57) + (57 + 57))", + multiplyBySquaring(Expr("57"), 4).expr, + "tried multiplyBySquaring(57, 4)" + ) + assertEquals( + "((-57 + -57) + (-57 + -57))", + multiplyBySquaring(Expr("57"), -4).expr, + "tried multiplyBySquaring(57, -4)" + ) + assertEquals( + "(57 + ((57 + 57) + (57 + 57)))", + multiplyBySquaring(Expr("57"), 5).expr, + "tried multiplyBySquaring(57, 5)" + ) + assertEquals( + "(-57 + ((-57 + -57) + (-57 + -57)))", + multiplyBySquaring(Expr("57"), -5).expr, + "tried multiplyBySquaring(57, -5)" + ) + assertEquals( + "((57 + 57) + ((57 + 57) + (57 + 57)))", + multiplyBySquaring(Expr("57"), 6).expr, + "tried multiplyBySquaring(57, 6)" + ) + assertEquals( + "((-57 + -57) + ((-57 + -57) + (-57 + -57)))", + multiplyBySquaring(Expr("57"), -6).expr, + "tried multiplyBySquaring(57, -6)" + ) + assertEquals( + "((57 + (57 + 57)) + ((57 + 57) + (57 + 57)))", + multiplyBySquaring(Expr("57"), 7).expr, + "tried multiplyBySquaring(57, 7)" + ) + assertEquals( + "((-57 + (-57 + -57)) + ((-57 + -57) + (-57 + -57)))", + multiplyBySquaring(Expr("57"), -7).expr, + "tried multiplyBySquaring(57, -7)" + ) + assertEquals( + "(((57 + 57) + (57 + 57)) + ((57 + 57) + (57 + 57)))", + multiplyBySquaring(Expr("57"), 8).expr, + "tried multiplyBySquaring(57, 8)" + ) + assertEquals( + "(((-57 + -57) + (-57 + -57)) + ((-57 + -57) + (-57 + -57)))", + multiplyBySquaring(Expr("57"), -8).expr, + "tried multiplyBySquaring(57, -8)" + ) + } + } + @Test + fun test_multiplyExponentiationBySquaring_for_UInt() { + ExprRing { + assertEquals( + "57", + multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 0u).expr, + "tried multiplyExponentiationBySquaring(57, 179, 0u)" + ) + assertEquals( + "(57 * 179)", + multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 1u).expr, + "tried multiplyExponentiationBySquaring(57, 179, 1u)" + ) + assertEquals( + "(57 * (179 * 179))", + multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 2u).expr, + "tried multiplyExponentiationBySquaring(57, 179, 2u)" + ) + assertEquals( + "((57 * 179) * (179 * 179))", + multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 3u).expr, + "tried multiplyExponentiationBySquaring(57, 179, 3u)" + ) + assertEquals( + "(57 * ((179 * 179) * (179 * 179)))", + multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 4u).expr, + "tried multiplyExponentiationBySquaring(57, 179, 4u)" + ) + assertEquals( + "((57 * 179) * ((179 * 179) * (179 * 179)))", + multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 5u).expr, + "tried multiplyExponentiationBySquaring(57, 179, 5u)" + ) + assertEquals( + "((57 * (179 * 179)) * ((179 * 179) * (179 * 179)))", + multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 6u).expr, + "tried multiplyExponentiationBySquaring(57, 179, 6u)" + ) + assertEquals( + "(((57 * 179) * (179 * 179)) * ((179 * 179) * (179 * 179)))", + multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 7u).expr, + "tried multiplyExponentiationBySquaring(57, 179, 7u)" + ) + assertEquals( + "(57 * (((179 * 179) * (179 * 179)) * ((179 * 179) * (179 * 179))))", + multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 8u).expr, + "tried multiplyExponentiationBySquaring(57, 179, 8u)" + ) + } + } + @Test + fun test_exponentiationBySquaring_for_UInt() { + ExprRing { + assertEquals( + "0", + exponentiationBySquaring(Expr("57"), 0u).expr, + "tried exponentiationBySquaring(57, 0u)" + ) + assertEquals( + "57", + exponentiationBySquaring(Expr("57"), 1u).expr, + "tried exponentiationBySquaring(57, 1u)" + ) + assertEquals( + "(57 * 57)", + exponentiationBySquaring(Expr("57"), 2u).expr, + "tried exponentiationBySquaring(57, 2u)" + ) + assertEquals( + "(57 * (57 * 57))", + exponentiationBySquaring(Expr("57"), 3u).expr, + "tried exponentiationBySquaring(57, 3u)" + ) + assertEquals( + "((57 * 57) * (57 * 57))", + exponentiationBySquaring(Expr("57"), 4u).expr, + "tried exponentiationBySquaring(57, 4u)" + ) + assertEquals( + "(57 * ((57 * 57) * (57 * 57)))", + exponentiationBySquaring(Expr("57"), 5u).expr, + "tried exponentiationBySquaring(57, 5u)" + ) + assertEquals( + "((57 * 57) * ((57 * 57) * (57 * 57)))", + exponentiationBySquaring(Expr("57"), 6u).expr, + "tried exponentiationBySquaring(57, 6u)" + ) + assertEquals( + "((57 * (57 * 57)) * ((57 * 57) * (57 * 57)))", + exponentiationBySquaring(Expr("57"), 7u).expr, + "tried exponentiationBySquaring(57, 7u)" + ) + assertEquals( + "(((57 * 57) * (57 * 57)) * ((57 * 57) * (57 * 57)))", + exponentiationBySquaring(Expr("57"), 8u).expr, + "tried exponentiationBySquaring(57, 8u)" + ) + } + } + @Test + fun test_multiplyExponentiationBySquaring_for_Int() { + ExprRing { + assertEquals( + "57", + multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 0).expr, + "tried multiplyExponentiationBySquaring(57, 179, 0)" + ) + assertEquals( + "(57 * 179)", + multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 1).expr, + "tried multiplyExponentiationBySquaring(57, 179, 1)" + ) + assertEquals( + "(57 * (1 / 179))", + multiplyExponentiationBySquaring(Expr("57"), Expr("179"), -1).expr, + "tried multiplyExponentiationBySquaring(57, 179, -1)" + ) + assertEquals( + "(57 * (179 * 179))", + multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 2).expr, + "tried multiplyExponentiationBySquaring(57, 179, 2)" + ) + assertEquals( + "(57 * ((1 / 179) * (1 / 179)))", + multiplyExponentiationBySquaring(Expr("57"), Expr("179"), -2).expr, + "tried multiplyExponentiationBySquaring(57, 179, -2)" + ) + assertEquals( + "((57 * 179) * (179 * 179))", + multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 3).expr, + "tried multiplyExponentiationBySquaring(57, 179, 3)" + ) + assertEquals( + "((57 * (1 / 179)) * ((1 / 179) * (1 / 179)))", + multiplyExponentiationBySquaring(Expr("57"), Expr("179"), -3).expr, + "tried multiplyExponentiationBySquaring(57, 179, -3)" + ) + assertEquals( + "(57 * ((179 * 179) * (179 * 179)))", + multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 4).expr, + "tried multiplyExponentiationBySquaring(57, 179, 4)" + ) + assertEquals( + "(57 * (((1 / 179) * (1 / 179)) * ((1 / 179) * (1 / 179))))", + multiplyExponentiationBySquaring(Expr("57"), Expr("179"), -4).expr, + "tried multiplyExponentiationBySquaring(57, 179, -4)" + ) + assertEquals( + "((57 * 179) * ((179 * 179) * (179 * 179)))", + multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 5).expr, + "tried multiplyExponentiationBySquaring(57, 179, 5)" + ) + assertEquals( + "((57 * (1 / 179)) * (((1 / 179) * (1 / 179)) * ((1 / 179) * (1 / 179))))", + multiplyExponentiationBySquaring(Expr("57"), Expr("179"), -5).expr, + "tried multiplyExponentiationBySquaring(57, 179, -5)" + ) + assertEquals( + "((57 * (179 * 179)) * ((179 * 179) * (179 * 179)))", + multiplyExponentiationBySquaring(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))))", + multiplyExponentiationBySquaring(Expr("57"), Expr("179"), -6).expr, + "tried multiplyExponentiationBySquaring(57, 179, -6)" + ) + assertEquals( + "(((57 * 179) * (179 * 179)) * ((179 * 179) * (179 * 179)))", + multiplyExponentiationBySquaring(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))))", + multiplyExponentiationBySquaring(Expr("57"), Expr("179"), -7).expr, + "tried multiplyExponentiationBySquaring(57, 179, -7)" + ) + assertEquals( + "(57 * (((179 * 179) * (179 * 179)) * ((179 * 179) * (179 * 179))))", + multiplyExponentiationBySquaring(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)))))", + multiplyExponentiationBySquaring(Expr("57"), Expr("179"), -8).expr, + "tried multiplyExponentiationBySquaring(57, 179, -8)" + ) + } + } + @Test + fun test_exponentiationBySquaring_for_Int() { + ExprRing { + assertEquals( + "0", + exponentiationBySquaring(Expr("57"), 0).expr, + "tried exponentiationBySquaring(57, 0)" + ) + assertEquals( + "57", + exponentiationBySquaring(Expr("57"), 1).expr, + "tried exponentiationBySquaring(57, 1)" + ) + assertEquals( + "(1 / 57)", + exponentiationBySquaring(Expr("57"), -1).expr, + "tried exponentiationBySquaring(57, -1)" + ) + assertEquals( + "(57 * 57)", + exponentiationBySquaring(Expr("57"), 2).expr, + "tried exponentiationBySquaring(57, 2)" + ) + assertEquals( + "((1 / 57) * (1 / 57))", + exponentiationBySquaring(Expr("57"), -2).expr, + "tried exponentiationBySquaring(57, -2)" + ) + assertEquals( + "(57 * (57 * 57))", + exponentiationBySquaring(Expr("57"), 3).expr, + "tried exponentiationBySquaring(57, 3)" + ) + assertEquals( + "((1 / 57) * ((1 / 57) * (1 / 57)))", + exponentiationBySquaring(Expr("57"), -3).expr, + "tried exponentiationBySquaring(57, -3)" + ) + assertEquals( + "((57 * 57) * (57 * 57))", + exponentiationBySquaring(Expr("57"), 4).expr, + "tried exponentiationBySquaring(57, 4)" + ) + assertEquals( + "(((1 / 57) * (1 / 57)) * ((1 / 57) * (1 / 57)))", + exponentiationBySquaring(Expr("57"), -4).expr, + "tried exponentiationBySquaring(57, -4)" + ) + assertEquals( + "(57 * ((57 * 57) * (57 * 57)))", + exponentiationBySquaring(Expr("57"), 5).expr, + "tried exponentiationBySquaring(57, 5)" + ) + assertEquals( + "((1 / 57) * (((1 / 57) * (1 / 57)) * ((1 / 57) * (1 / 57))))", + exponentiationBySquaring(Expr("57"), -5).expr, + "tried exponentiationBySquaring(57, -5)" + ) + assertEquals( + "((57 * 57) * ((57 * 57) * (57 * 57)))", + exponentiationBySquaring(Expr("57"), 6).expr, + "tried exponentiationBySquaring(57, 6)" + ) + assertEquals( + "(((1 / 57) * (1 / 57)) * (((1 / 57) * (1 / 57)) * ((1 / 57) * (1 / 57))))", + exponentiationBySquaring(Expr("57"), -6).expr, + "tried exponentiationBySquaring(57, -6)" + ) + assertEquals( + "((57 * (57 * 57)) * ((57 * 57) * (57 * 57)))", + exponentiationBySquaring(Expr("57"), 7).expr, + "tried exponentiationBySquaring(57, 7)" + ) + assertEquals( + "(((1 / 57) * ((1 / 57) * (1 / 57))) * (((1 / 57) * (1 / 57)) * ((1 / 57) * (1 / 57))))", + exponentiationBySquaring(Expr("57"), -7).expr, + "tried exponentiationBySquaring(57, -7)" + ) + assertEquals( + "(((57 * 57) * (57 * 57)) * ((57 * 57) * (57 * 57)))", + exponentiationBySquaring(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))))", + exponentiationBySquaring(Expr("57"), -8).expr, + "tried exponentiationBySquaring(57, -8)" + ) + } + } +} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt index e0f0e32a4..a11242b2a 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt @@ -12,11 +12,12 @@ import kotlin.test.assertEquals class PolynomialTest { @Test fun simple_polynomial_test() { + val polynomial : Polynomial Double.algebra.scalablePolynomial { val x = Polynomial(listOf(0.0, 1.0)) - val polynomial = x * x - 2 * x + 1 - assertEquals(0.0, polynomial.substitute(1.0), 0.001) + polynomial = x * x - 2 * x + 1 } + assertEquals(0.0, polynomial.substitute(1.0), 0.001) } @Test fun testIntegration() { -- 2.34.1 From a965f5683f055daf20058f81e62fc8cc16e48141 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sat, 19 Mar 2022 16:54:30 +0300 Subject: [PATCH 045/275] Added some tests and some utilities for tests. Fixed bug in utility of PolynomialSpace. --- .../kscience/kmath/functions/Polynomial.kt | 8 +- .../kmath/functions/PolynomialTest.kt | 67 +++ .../kscience/kmath/test/misc/Rational.kt | 387 ++++++++++++++++++ .../test/misc/RationalWithMemorization.kt | 113 +++++ .../kscience/kmath/test/misc/memorization.kt | 51 +++ .../space/kscience/kmath/test/misc/misc.kt | 25 ++ 6 files changed, 647 insertions(+), 4 deletions(-) create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/RationalWithMemorization.kt create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/memorization.kt create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index a60ca563a..3f0d073b3 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -447,7 +447,7 @@ public open class PolynomialSpace>( callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block() - while (elementAt(lastIndex).isZero()) removeAt(lastIndex) + while (isNotEmpty() && elementAt(lastIndex).isZero()) removeAt(lastIndex) return this } internal inline fun List.applyAndRemoveZeros(block: MutableList.() -> Unit) : List = @@ -456,7 +456,7 @@ public open class PolynomialSpace>( internal inline fun MutableCoefficients(size: Int, init: (index: Int) -> C): MutableList { val list = ArrayList(size) repeat(size) { index -> list.add(init(index)) } - with(list) { while (elementAt(lastIndex).isZero()) removeAt(lastIndex) } + with(list) { while (isNotEmpty() && elementAt(lastIndex).isZero()) removeAt(lastIndex) } return list } @Suppress("FunctionName") @@ -466,7 +466,7 @@ public open class PolynomialSpace>( contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } return buildList { builderAction() - while (elementAt(lastIndex).isZero()) removeAt(lastIndex) + while (isNotEmpty() && elementAt(lastIndex).isZero()) removeAt(lastIndex) } } @OptIn(ExperimentalTypeInference::class) @@ -474,7 +474,7 @@ public open class PolynomialSpace>( contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } return buildList(capacity) { builderAction() - while (elementAt(lastIndex).isZero()) removeAt(lastIndex) + while (isNotEmpty() && elementAt(lastIndex).isZero()) removeAt(lastIndex) } } } diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt index a11242b2a..9e3dea615 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt @@ -5,11 +5,78 @@ package space.kscience.kmath.functions +import space.kscience.kmath.operations.BigInt import space.kscience.kmath.operations.algebra +import space.kscience.kmath.operations.toBigInt +import space.kscience.kmath.test.misc.Rational +import space.kscience.kmath.test.misc.RationalField +import space.kscience.kmath.test.misc.gcd import kotlin.test.Test import kotlin.test.assertEquals class PolynomialTest { + @Test + fun test_Polynomial_Polynomial_plus() { + RationalField.polynomial { + // (5/9 - 8/9 x - 8/7 x^2) + (-5/7 + 5/1 x + 5/8 x^2) ?= -10/63 + 37/9 x - 29/56 x^2 + assertEquals( + Polynomial(Rational(-10, 63), Rational(37, 9), Rational(-29, 56)), + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + + Polynomial(Rational(-5, 7), Rational(5, 1), Rational(5, 8)), + "test 1" + ) + // (-2/9 - 8/3 x) + (0 + 9/4 x + 2/4 x^2) ?= -2/9 - 5/12 x + 2/4 x^2 + assertEquals( + Polynomial(Rational(-2, 9), Rational(-5, 12), Rational(2, 4)), + Polynomial(Rational(-2, 9), Rational(-8, 3)) + + Polynomial(Rational(0), Rational(9, 4), Rational(2, 4)), + "test 2" + ) + // (-4/7 - 2/6 x + 0 x^2 + 0 x^3) + (-6/3 - 7/2 x + 2/3 x^2) ?= -18/7 - 23/6 x + 2/3 x^2 + assertEquals( + Polynomial(Rational(-18, 7), Rational(-23, 6), Rational(2, 3)), + Polynomial(Rational(-4, 7), Rational(-2, 6), Rational(0), Rational(0)) + + Polynomial(Rational(-6, 3), Rational(-7, 2), Rational(2, 3)), + "test 3" + ) + // (-2/4 - 6/9 x - 4/9 x^2) + (2/4 + 6/9 x + 4/9 x^2) ?= 0 + assertEquals( + Polynomial(), + Polynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)) + + Polynomial(Rational(2, 4), Rational(6, 9), Rational(4, 9)), + "test 4" + ) + } + } +// @Test +// fun test_Polynomial_Polynomial_minus() { +// RationalField.polynomial { +// assertEquals( +// Polynomial(Rational(1, 2), Rational(3, 5), Rational(-2)) + +// Polynomial(Rational(3), Rational(7, 8), Rational(1, 9)), +// Polynomial(Rational(7, 2), Rational(59, 40), Rational(-17, 9)), +// "test 1" +// ) +// assertEquals( +// Polynomial(Rational(1, 2), Rational(3, 5)) + +// Polynomial(Rational(3), Rational(7, 8), Rational(1, 9)), +// Polynomial(Rational(7, 2), Rational(59, 40), Rational(1, 9)), +// "test 2" +// ) +// assertEquals( +// Polynomial(Rational(1, 2), Rational(3, 5), Rational(0), Rational(0)) + +// Polynomial(Rational(3), Rational(7, 8), Rational(1, 9)), +// Polynomial(Rational(7, 2), Rational(59, 40), Rational(1, 9)), +// "test 3" +// ) +// assertEquals( +// Polynomial(Rational(1, 2), Rational(-3, 5), Rational(7, 3)) + +// Polynomial(Rational(3), Rational(3, 5), Rational(-7, 3)), +// Polynomial(Rational(7, 2)), +// "test 4" +// ) +// } +// } @Test fun simple_polynomial_test() { val polynomial : Polynomial diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt new file mode 100644 index 000000000..fad13f88a --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt @@ -0,0 +1,387 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.test.misc + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.BigInt +import space.kscience.kmath.operations.Field +import space.kscience.kmath.operations.NumbersAddOps +import space.kscience.kmath.operations.toBigInt +import space.kscience.kmath.operations.BigInt.Companion.ZERO as I0 +import space.kscience.kmath.operations.BigInt.Companion.ONE as I1 + +/** + * The class represents rational numbers. + * + * Instances contain [numerator] and [denominator] represented as [Long]. + * + * Also [numerator] and [denominator] are coprime and [denominator] is positive. + * + * @author [Gleb Minaev](https://github.com/lounres) + */ +public class Rational: Comparable { + public companion object { + /** + * Constant containing the zero (the additive identity) of the [Rational] field. + */ + public val ZERO: Rational = Rational(I0) + /** + * Constant containing the one (the multiplicative identity) of the [Rational] field. + */ + public val ONE: Rational = Rational(I1) + } + + /** + * Numerator of the fraction. It's stored as non-negative coprime with [denominator] integer. + */ + public val numerator: BigInt + /** + * Denominator of the fraction. It's stored as non-zero coprime with [numerator] integer. + */ + public val denominator: BigInt + + /** + * If [toCheckInput] is `true` before assigning values to [Rational.numerator] and [Rational.denominator] makes them coprime and makes + * denominator positive. Otherwise, just assigns the values. + * + * @throws ArithmeticException If denominator is zero. + */ + internal constructor(numerator: BigInt, denominator: BigInt, toCheckInput: Boolean = true) { + if (toCheckInput) { + if (denominator == I0) throw ArithmeticException("/ by zero") + + val greatestCommonDivider = gcd(numerator, denominator).let { if (denominator < I0) -it else it } + + this.numerator = numerator / greatestCommonDivider + this.denominator = denominator / greatestCommonDivider + } else { + this.numerator = numerator + this.denominator = denominator + } + } + + /** + * Before assigning values to [Rational.numerator] and [Rational.denominator] makes them coprime and makes + * denominator positive. + * + * @throws ArithmeticException If denominator is zero. + */ + public constructor(numerator: BigInt, denominator: BigInt) : this(numerator, denominator, true) + public constructor(numerator: Int, denominator: BigInt) : this(numerator.toBigInt(), denominator, true) + public constructor(numerator: Long, denominator: BigInt) : this(numerator.toBigInt(), denominator, true) + public constructor(numerator: BigInt, denominator: Int) : this(numerator, denominator.toBigInt(), true) + public constructor(numerator: BigInt, denominator: Long) : this(numerator, denominator.toBigInt(), true) + public constructor(numerator: Int, denominator: Int) : this(numerator.toBigInt(), denominator.toBigInt(), true) + public constructor(numerator: Int, denominator: Long) : this(numerator.toBigInt(), denominator.toBigInt(), true) + public constructor(numerator: Long, denominator: Int) : this(numerator.toBigInt(), denominator.toBigInt(), true) + public constructor(numerator: Long, denominator: Long) : this(numerator.toBigInt(), denominator.toBigInt(), true) + public constructor(numerator: BigInt) : this(numerator, I1, false) + public constructor(numerator: Int) : this(numerator.toBigInt(), I1, false) + public constructor(numerator: Long) : this(numerator.toBigInt(), I1, false) + + /** + * Returns the same instant. + */ + public operator fun unaryPlus(): Rational = this + + /** + * Returns negation of the instant of [Rational] field. + */ + public operator fun unaryMinus(): Rational = Rational(-this.numerator, this.denominator) + + /** + * Returns sum of the instants of [Rational] field. + */ + public operator fun plus(other: Rational): Rational = + Rational( + numerator * other.denominator + denominator * other.numerator, + denominator * other.denominator + ) + + /** + * Returns sum of the instants of [Rational] field. [other] is represented as [Rational]. + */ + public operator fun plus(other: BigInt): Rational = + Rational( + numerator + denominator * other, + denominator + ) + + /** + * Returns sum of the instants of [Rational] field. [other] is represented as [Rational]. + */ + public operator fun plus(other: Int): Rational = + Rational( + numerator + denominator * other.toBigInt(), + denominator + ) + + /** + * Returns sum of the instants of [Rational] field. [other] is represented as [Rational]. + */ + public operator fun plus(other: Long): Rational = + Rational( + numerator + denominator * other.toBigInt(), + denominator + ) + + /** + * Returns difference of the instants of [Rational] field. + */ + public operator fun minus(other: Rational): Rational = + Rational( + numerator * other.denominator - denominator * other.numerator, + denominator * other.denominator + ) + + /** + * Returns difference of the instants of [Rational] field. [other] is represented as [Rational]. + */ + public operator fun minus(other: BigInt): Rational = + Rational( + numerator - denominator * other, + denominator + ) + + /** + * Returns difference of the instants of [Rational] field. [other] is represented as [Rational]. + */ + public operator fun minus(other: Int): Rational = + Rational( + numerator - denominator * other.toBigInt(), + denominator + ) + + /** + * Returns difference of the instants of [Rational] field. [other] is represented as [Rational]. + */ + public operator fun minus(other: Long): Rational = + Rational( + numerator - denominator * other.toBigInt(), + denominator + ) + + /** + * Returns product of the instants of [Rational] field. + */ + public operator fun times(other: Rational): Rational = + Rational( + numerator * other.numerator, + denominator * other.denominator + ) + + /** + * Returns product of the instants of [Rational] field. [other] is represented as [Rational]. + */ + public operator fun times(other: BigInt): Rational = + Rational( + numerator * other, + denominator + ) + + /** + * Returns product of the instants of [Rational] field. [other] is represented as [Rational]. + */ + public operator fun times(other: Int): Rational = + Rational( + numerator * other.toBigInt(), + denominator + ) + + /** + * Returns product of the instants of [Rational] field. [other] is represented as [Rational]. + */ + public operator fun times(other: Long): Rational = + Rational( + numerator * other.toBigInt(), + denominator + ) + + /** + * Returns quotient of the instants of [Rational] field. + * + * @throws ArithmeticException if [other] is the zero of the field it can't be a divisor. + */ + public operator fun div(other: Rational): Rational = + Rational( + numerator * other.denominator, + denominator * other.numerator + ) + + /** + * Returns quotient of the instants of [Rational] field. [other] is represented as [Rational]. + * + * @throws ArithmeticException if [other] is the zero of the field it can't be a divisor. + */ + public operator fun div(other: BigInt): Rational = + Rational( + numerator, + denominator * other + ) + + /** + * Returns quotient of the instants of [Rational] field. [other] is represented as [Rational]. + * + * @throws ArithmeticException if [other] is the zero of the field it can't be a divisor. + */ + public operator fun div(other: Int): Rational = + Rational( + numerator, + denominator * other.toBigInt() + ) + + /** + * Returns quotient of the instants of [Rational] field. [other] is represented as [Rational]. + * + * @throws ArithmeticException if [other] is the zero of the field it can't be a divisor. + */ + public operator fun div(other: Long): Rational = + Rational( + numerator, + denominator * other.toBigInt() + ) + + /** + * Returns reminder from integral division. + * + * @throws ArithmeticException if [other] is the zero of the field it can't be a divisor. + */ + public operator fun rem(other: Rational): Rational = + Rational( + (numerator * other.denominator) % (denominator * other.numerator), + denominator * other.denominator + ) + + /** + * Returns reminder from integral division. + * + * @throws ArithmeticException if [other] is the zero of the field it can't be a divisor. + */ + public operator fun rem(other: BigInt): Rational = + Rational( + numerator % denominator * other, + denominator * other + ) + + /** + * Returns reminder from integral division. + * + * @throws ArithmeticException if [other] is the zero of the field it can't be a divisor. + */ + public operator fun rem(other: Int): Rational = + Rational( + numerator % denominator * other.toBigInt(), + denominator * other.toBigInt() + ) + + /** + * Returns reminder from integral division. + * + * @throws ArithmeticException if [other] is the zero of the field it can't be a divisor. + */ + public operator fun rem(other: Long): Rational = + Rational( + numerator % denominator * other.toBigInt(), + denominator * other.toBigInt() + ) + + /** + * Checks equality of the instance to [other]. + * + * [BigInt], [Int] and [Long] values are also checked as Rational ones. + */ + override fun equals(other: Any?): Boolean = + when (other) { + is Rational -> numerator == other.numerator && denominator == other.denominator + is BigInt -> numerator == other && denominator == I1 + is Int -> numerator == other && denominator == I1 + is Long -> numerator == other && denominator == I1 + else -> false + } + + /** + * Compares the instance to [other] as [Comparable.compareTo]. + * + * @see Comparable.compareTo + */ + override operator fun compareTo(other: Rational): Int = (numerator * other.denominator).compareTo(other.numerator * denominator) + + /** + * Compares the instance to [other] as [Comparable.compareTo]. + * + * [Integer] values are also checked as Rational ones. + * + * @see Comparable.compareTo + */ + public operator fun compareTo(other: BigInt): Int = (numerator).compareTo(denominator * other) + + /** + * Compares the instance to [other] as [Comparable.compareTo]. + * + * [Int] values are also checked as Rational ones. + * + * @see Comparable.compareTo + */ + public operator fun compareTo(other: Int): Int = (numerator).compareTo(denominator * other.toBigInt()) + + /** + * Compares the instance to [other] as [Comparable.compareTo]. + * + * [Long] values are also checked as Rational ones. + * + * @see Comparable.compareTo + */ + public operator fun compareTo(other: Long): Int = (numerator).compareTo(denominator * other.toBigInt()) + + public override fun hashCode(): Int = 31 * numerator.hashCode() + denominator.hashCode() + +// /** Creates a range from this value to the specified [other] value. */ +// operator fun rangeTo(other: JBInt) = ClosedRationalRange(this, other.toRational()) +// /** Creates a range from this value to the specified [other] value. */ +// operator fun rangeTo(other: Rational) = ClosedRationalRange(this, other) +// /** Creates a range from this value to the specified [other] value. */ +// operator fun rangeTo(other: Int) = ClosedRationalRange(this, other.toRational()) +// /** Creates a range from this value to the specified [other] value. */ +// operator fun rangeTo(other: Long) = ClosedRationalRange(this, other.toRational()) + + public fun toRational(): Rational = this + + public fun toBigInt(): BigInt = numerator / denominator + +// public fun toInt(): Int = (numerator / denominator).toInt() +// +// public fun toLong(): Long = (numerator / denominator).toLong() +// +// public fun toDouble(): Double = (numerator.toDouble() / denominator.toDouble()) +// +// public fun toFloat(): Float = (numerator.toFloat() / denominator.toFloat()) + + public override fun toString(): String = if (denominator == I1) "$numerator" else "$numerator/$denominator" +} + + +/** + * Algebraic structure for rational numbers. + */ +@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") +@OptIn(UnstableKMathAPI::class) +public object RationalField : Field, NumbersAddOps { + override inline val zero: Rational get() = Rational.ZERO + override inline val one: Rational get() = Rational.ONE + + override inline fun number(value: Number): Rational = Rational(value.toLong()) + + override inline fun add(left: Rational, right: Rational): Rational = left + right + override inline fun multiply(left: Rational, right: Rational): Rational = left * right + override inline fun divide(left: Rational, right: Rational): Rational = left / right + override inline fun scale(a: Rational, value: Double): Rational = a * number(value) + + override inline fun Rational.unaryMinus(): Rational = -this + override inline fun Rational.plus(arg: Rational): Rational = this + arg + override inline fun Rational.minus(arg: Rational): Rational = this - arg + override inline fun Rational.times(arg: Rational): Rational = this * arg + override inline fun Rational.div(arg: Rational): Rational = this / arg +} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/RationalWithMemorization.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/RationalWithMemorization.kt new file mode 100644 index 000000000..6aa5ecc09 --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/RationalWithMemorization.kt @@ -0,0 +1,113 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.test.misc + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.* + +class RationalWithMemorization private constructor( + val value: Rational, + override val memory : OperationsMemory +): WithMemorization { + public companion object { + /** + * Constant containing the zero (the additive identity) of the [Rational] field. + */ + public val ZERO: RationalWithMemorization = RationalWithMemorization(Rational.ZERO, object : Endpoint {}) + /** + * Constant containing the one (the multiplicative identity) of the [Rational] field. + */ + public val ONE: RationalWithMemorization = RationalWithMemorization(Rational.ONE, object : Endpoint {}) + } + public constructor(numerator: BigInt, denominator: BigInt) : this(Rational(numerator, denominator), object : Endpoint {}) + public constructor(numerator: Int, denominator: BigInt) : this(Rational(numerator, denominator), object : Endpoint {}) + public constructor(numerator: Long, denominator: BigInt) : this(Rational(numerator, denominator), object : Endpoint {}) + public constructor(numerator: BigInt, denominator: Int) : this(Rational(numerator, denominator), object : Endpoint {}) + public constructor(numerator: BigInt, denominator: Long) : this(Rational(numerator, denominator), object : Endpoint {}) + public constructor(numerator: Int, denominator: Int) : this(Rational(numerator, denominator), object : Endpoint {}) + public constructor(numerator: Int, denominator: Long) : this(Rational(numerator, denominator), object : Endpoint {}) + public constructor(numerator: Long, denominator: Int) : this(Rational(numerator, denominator), object : Endpoint {}) + public constructor(numerator: Long, denominator: Long) : this(Rational(numerator, denominator), object : Endpoint {}) + public constructor(numerator: BigInt) : this(Rational(numerator), object : Endpoint {}) + public constructor(numerator: Int) : this(Rational(numerator), object : Endpoint {}) + public constructor(numerator: Long) : this(Rational(numerator), object : Endpoint {}) + + public operator fun unaryPlus(): RationalWithMemorization = this + public operator fun unaryMinus(): RationalWithMemorization = RationalWithMemorization( + -value, + object : Negation { + override val negated: OperationsMemory = memory + } + ) + public operator fun plus(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization( + value + other.value, + object : Sum { + override val augend: OperationsMemory = memory + override val addend: OperationsMemory = other.memory + } + ) + public operator fun minus(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization( + value - other.value, + object : Difference { + override val minuend: OperationsMemory = memory + override val subtrahend: OperationsMemory = other.memory + } + ) + public operator fun times(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization( + value * other.value, + object : Product { + override val multiplicand: OperationsMemory = memory + override val multiplier: OperationsMemory = other.memory + } + ) + public operator fun div(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization( + value / other.value, + object : Quotient { + override val dividend: OperationsMemory = memory + override val divisor: OperationsMemory = other.memory + } + ) + + public override fun equals(other: Any?): Boolean = + other is RationalWithMemorization && value == other.value + + public override fun hashCode(): Int = value.hashCode() + + public override fun toString(): String = value.toString() +} + +@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") +public object RationalWithMemorizationRing : Ring { + override inline val zero: RationalWithMemorization get() = RationalWithMemorization.ZERO + override inline val one: RationalWithMemorization get() = RationalWithMemorization.ONE + + override inline fun add(left: RationalWithMemorization, right: RationalWithMemorization): RationalWithMemorization = left + right + override inline fun multiply(left: RationalWithMemorization, right: RationalWithMemorization): RationalWithMemorization = left * right + + override inline fun RationalWithMemorization.unaryMinus(): RationalWithMemorization = -this + override inline fun RationalWithMemorization.plus(arg: RationalWithMemorization): RationalWithMemorization = this + arg + override inline fun RationalWithMemorization.minus(arg: RationalWithMemorization): RationalWithMemorization = this - arg + override inline fun RationalWithMemorization.times(arg: RationalWithMemorization): RationalWithMemorization = this * arg +} + +@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") +public object RationalWithMemorizationField : Field { + override inline val zero: RationalWithMemorization get() = RationalWithMemorization.ZERO + override inline val one: RationalWithMemorization get() = RationalWithMemorization.ONE + + override inline fun number(value: Number): RationalWithMemorization = RationalWithMemorization(value.toLong()) + + override inline fun add(left: RationalWithMemorization, right: RationalWithMemorization): RationalWithMemorization = left + right + override inline fun multiply(left: RationalWithMemorization, right: RationalWithMemorization): RationalWithMemorization = left * right + override inline fun divide(left: RationalWithMemorization, right: RationalWithMemorization): RationalWithMemorization = left / right + override inline fun scale(a: RationalWithMemorization, value: Double): RationalWithMemorization = a * number(value) + + override inline fun RationalWithMemorization.unaryMinus(): RationalWithMemorization = -this + override inline fun RationalWithMemorization.plus(arg: RationalWithMemorization): RationalWithMemorization = this + arg + override inline fun RationalWithMemorization.minus(arg: RationalWithMemorization): RationalWithMemorization = this - arg + override inline fun RationalWithMemorization.times(arg: RationalWithMemorization): RationalWithMemorization = this * arg + override inline fun RationalWithMemorization.div(arg: RationalWithMemorization): RationalWithMemorization = this / arg +} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/memorization.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/memorization.kt new file mode 100644 index 000000000..a4fb81274 --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/memorization.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.test.misc + +sealed interface OperationsMemory + +interface Endpoint: OperationsMemory + +interface Negation: OperationsMemory { + val negated: OperationsMemory +} + +interface Sum: OperationsMemory { + val augend: OperationsMemory + val addend: OperationsMemory +} + +interface Difference: OperationsMemory { + val minuend: OperationsMemory + val subtrahend: OperationsMemory +} + +interface Product: OperationsMemory { + val multiplicand: OperationsMemory + val multiplier: OperationsMemory +} + +interface Quotient: OperationsMemory { + val dividend: OperationsMemory + val divisor: OperationsMemory +} + + +fun equalMemories(one: OperationsMemory, other: OperationsMemory) : Boolean = + when(one) { + is Negation -> other is Negation && equalMemories(one.negated, other.negated) + is Sum -> other is Sum && equalMemories(one.augend, other.augend) && equalMemories(one.addend, other.addend) + is Difference -> other is Difference && equalMemories(one.minuend, other.minuend) && equalMemories(one.subtrahend, other.subtrahend) + is Product -> other is Product && equalMemories(one.multiplicand, other.multiplicand) && equalMemories(one.multiplier, other.multiplier) + is Quotient -> other is Quotient && equalMemories(one.dividend, other.dividend) && equalMemories(one.divisor, other.divisor) + is Endpoint -> one === other + } + +interface WithMemorization { + val memory: OperationsMemory +} + +fun equalMemories(one: WithMemorization, other: WithMemorization) : Boolean = equalMemories(one.memory, other.memory) \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt new file mode 100644 index 000000000..eab29842c --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.test.misc + +import space.kscience.kmath.operations.* +import space.kscience.kmath.operations.BigInt.Companion.ZERO as I0 + +// TODO: Move to corresponding module "kmath-number-theory" + +/** + * Computes [Greatest Common Divisor](https://en.wikipedia.org/wiki/Greatest_common_divisor) of [a] and [b]. + * + * It's computed by [Euclidean algorithm](https://en.wikipedia.org/wiki/Greatest_common_divisor#Euclidean_algorithm). + * Hence, its time complexity is $$O(\log(a+b))$$ (see [Wolfram MathWorld](https://mathworld.wolfram.com/EuclideanAlgorithm.html)). + */ +public tailrec fun gcd(a: BigInt, b: BigInt): BigInt = if (a == I0) abs(b) else gcd(b % a, a) + +/** + * Computes [Greatest Common Divisor](https://en.wikipedia.org/wiki/Greatest_common_divisor) of the [values]. + */ +public fun gcd(vararg values: BigInt): BigInt = values.reduce(::gcd) +public fun gcd(values: Iterable): BigInt = values.reduce(::gcd) \ No newline at end of file -- 2.34.1 From 90a7c4d901d6383b2de5326b0fa852f27bc47320 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sat, 19 Mar 2022 18:08:43 +0300 Subject: [PATCH 046/275] Simplified use of Rational (current BigInt are hard to use and actually useless). Added tests, fixed bug. --- .../kmath/functions/NumberedPolynomial.kt | 8 +- .../kscience/kmath/functions/Polynomial.kt | 2 +- .../kmath/functions/PolynomialTest.kt | 225 +++++++++-- .../kscience/kmath/test/misc/Rational.kt | 348 +++--------------- .../test/misc/RationalWithMemorization.kt | 42 +-- .../space/kscience/kmath/test/misc/misc.kt | 17 +- 6 files changed, 268 insertions(+), 374 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index 88349f003..c05bc30ec 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -246,7 +246,7 @@ public open class NumberedPolynomialSpace>( override operator fun C.minus(other: NumberedPolynomial): NumberedPolynomial = if (this.isZero()) -other else with(other.coefficients) { - if (isEmpty()) NumberedPolynomial(mapOf(listOf() to this@minus)) + if (isEmpty()) NumberedPolynomial(mapOf(emptyList() to this@minus)) else NumberedPolynomial( toMutableMap() .apply { @@ -279,7 +279,7 @@ public open class NumberedPolynomialSpace>( override operator fun NumberedPolynomial.plus(other: C): NumberedPolynomial = if (other.isZero()) this else with(coefficients) { - if (isEmpty()) NumberedPolynomial(mapOf(listOf() to other)) + if (isEmpty()) NumberedPolynomial(mapOf(emptyList() to other)) else NumberedPolynomial( toMutableMap() .apply { @@ -298,7 +298,7 @@ public open class NumberedPolynomialSpace>( override operator fun NumberedPolynomial.minus(other: C): NumberedPolynomial = if (other.isZero()) this else with(coefficients) { - if (isEmpty()) NumberedPolynomial(mapOf(listOf() to other)) + if (isEmpty()) NumberedPolynomial(mapOf(emptyList() to other)) else NumberedPolynomial( toMutableMap() .apply { @@ -416,7 +416,7 @@ public open class NumberedPolynomialSpace>( override val one: NumberedPolynomial = NumberedPolynomial( mapOf( - listOf() to constantOne // 1 * x_1^0 * x_2^0 * ... + emptyList() to constantOne // 1 * x_1^0 * x_2^0 * ... ) ) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 3f0d073b3..722566f5d 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -276,7 +276,7 @@ public open class PolynomialSpace>( public override operator fun Polynomial.minus(other: C): Polynomial = if (other.isZero()) this else with(coefficients) { - if (isEmpty()) Polynomial(listOf(other)) + if (isEmpty()) Polynomial(listOf(-other)) else Polynomial( toMutableList() .apply { diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt index 9e3dea615..e2970d953 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt @@ -5,16 +5,173 @@ package space.kscience.kmath.functions -import space.kscience.kmath.operations.BigInt import space.kscience.kmath.operations.algebra -import space.kscience.kmath.operations.toBigInt import space.kscience.kmath.test.misc.Rational import space.kscience.kmath.test.misc.RationalField -import space.kscience.kmath.test.misc.gcd import kotlin.test.Test import kotlin.test.assertEquals class PolynomialTest { + @Test + fun test_Polynomial_Int_plus() { + RationalField.polynomial { + assertEquals( + Polynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)), + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + -3, + "test 1" + ) + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + 2, + "test 2" + ) + assertEquals( + Polynomial(), + Polynomial(Rational(-2)) + 2, + "test 3" + ) + assertEquals( + Polynomial(), + Polynomial() + 0, + "test 4" + ) + assertEquals( + Polynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), + Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + 1, + "test 5" + ) + assertEquals( + Polynomial(Rational(-1)), + Polynomial(Rational(-2)) + 1, + "test 6" + ) + assertEquals( + Polynomial(Rational(2)), + Polynomial() + 2, + "test 7" + ) + } + } + @Test + fun test_Polynomial_Int_minus() { + RationalField.polynomial { + assertEquals( + Polynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - -3, + "test 1" + ) + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + Polynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - 2, + "test 2" + ) + assertEquals( + Polynomial(), + Polynomial(Rational(2)) - 2, + "test 3" + ) + assertEquals( + Polynomial(), + Polynomial() - 0, + "test 4" + ) + assertEquals( + Polynomial(Rational(1), Rational(0), Rational(0), Rational(0)), + Polynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - 1, + "test 5" + ) + assertEquals( + Polynomial(Rational(1)), + Polynomial(Rational(2)) - 1, + "test 6" + ) + assertEquals( + Polynomial(Rational(-2)), + Polynomial() - 2, + "test 7" + ) + } + } + @Test + fun test_Polynomial_Constant_plus() { + RationalField.polynomial { + assertEquals( + Polynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)), + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + Rational(-3), + "test 1" + ) + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + Rational(2), + "test 2" + ) + assertEquals( + Polynomial(), + Polynomial(Rational(-2)) + Rational(2), + "test 3" + ) + assertEquals( + Polynomial(), + Polynomial() + Rational(0), + "test 4" + ) + assertEquals( + Polynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), + Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + Rational(1), + "test 5" + ) + assertEquals( + Polynomial(Rational(-1)), + Polynomial(Rational(-2)) + Rational(1), + "test 6" + ) + assertEquals( + Polynomial(Rational(2)), + Polynomial() + Rational(2), + "test 7" + ) + } + } + @Test + fun test_Polynomial_Constant_minus() { + RationalField.polynomial { + assertEquals( + Polynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - Rational(-3), + "test 1" + ) + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + Polynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - Rational(2), + "test 2" + ) + assertEquals( + Polynomial(), + Polynomial(Rational(2)) - Rational(2), + "test 3" + ) + assertEquals( + Polynomial(), + Polynomial() - Rational(0), + "test 4" + ) + assertEquals( + Polynomial(Rational(1), Rational(0), Rational(0), Rational(0)), + Polynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - Rational(1), + "test 5" + ) + assertEquals( + Polynomial(Rational(1)), + Polynomial(Rational(2)) - Rational(1), + "test 6" + ) + assertEquals( + Polynomial(Rational(-2)), + Polynomial() - Rational(2), + "test 7" + ) + } + } @Test fun test_Polynomial_Polynomial_plus() { RationalField.polynomial { @@ -48,35 +205,39 @@ class PolynomialTest { ) } } -// @Test -// fun test_Polynomial_Polynomial_minus() { -// RationalField.polynomial { -// assertEquals( -// Polynomial(Rational(1, 2), Rational(3, 5), Rational(-2)) + -// Polynomial(Rational(3), Rational(7, 8), Rational(1, 9)), -// Polynomial(Rational(7, 2), Rational(59, 40), Rational(-17, 9)), -// "test 1" -// ) -// assertEquals( -// Polynomial(Rational(1, 2), Rational(3, 5)) + -// Polynomial(Rational(3), Rational(7, 8), Rational(1, 9)), -// Polynomial(Rational(7, 2), Rational(59, 40), Rational(1, 9)), -// "test 2" -// ) -// assertEquals( -// Polynomial(Rational(1, 2), Rational(3, 5), Rational(0), Rational(0)) + -// Polynomial(Rational(3), Rational(7, 8), Rational(1, 9)), -// Polynomial(Rational(7, 2), Rational(59, 40), Rational(1, 9)), -// "test 3" -// ) -// assertEquals( -// Polynomial(Rational(1, 2), Rational(-3, 5), Rational(7, 3)) + -// Polynomial(Rational(3), Rational(3, 5), Rational(-7, 3)), -// Polynomial(Rational(7, 2)), -// "test 4" -// ) -// } -// } + @Test + fun test_Polynomial_Polynomial_minus() { + RationalField.polynomial { + // (5/9 - 8/9 x - 8/7 x^2) - (-5/7 + 5/1 x + 5/8 x^2) ?= 80/63 - 53/9 x - 99/56 x^2 + assertEquals( + Polynomial(Rational(80, 63), Rational(-53, 9), Rational(-99, 56)), + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - + Polynomial(Rational(-5, 7), Rational(5, 1), Rational(5, 8)), + "test 1" + ) + // (-2/9 - 8/3 x) - (0 + 9/4 x + 2/4 x^2) ?= -2/9 - 59/12 x - 2/4 x^2 + assertEquals( + Polynomial(Rational(-2, 9), Rational(-59, 12), Rational(-2, 4)), + Polynomial(Rational(-2, 9), Rational(-8, 3)) - + Polynomial(Rational(0), Rational(9, 4), Rational(2, 4)), + "test 2" + ) + // (-4/7 - 2/6 x + 0 x^2 + 0 x^3) - (-6/3 - 7/2 x + 2/3 x^2) ?= 10/7 + 19/6 x - 2/3 x^2 + assertEquals( + Polynomial(Rational(10, 7), Rational(19, 6), Rational(-2, 3)), + Polynomial(Rational(-4, 7), Rational(-2, 6), Rational(0), Rational(0)) - + Polynomial(Rational(-6, 3), Rational(-7, 2), Rational(2, 3)), + "test 3" + ) + // (-2/4 - 6/9 x - 4/9 x^2) - (-2/4 - 6/9 x - 4/9 x^2) ?= 0 + assertEquals( + Polynomial(), + Polynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)) - + Polynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)), + "test 4" + ) + } + } @Test fun simple_polynomial_test() { val polynomial : Polynomial diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt index fad13f88a..842e354db 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt @@ -6,54 +6,23 @@ package space.kscience.kmath.test.misc import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.BigInt import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.NumbersAddOps -import space.kscience.kmath.operations.toBigInt -import space.kscience.kmath.operations.BigInt.Companion.ZERO as I0 -import space.kscience.kmath.operations.BigInt.Companion.ONE as I1 -/** - * The class represents rational numbers. - * - * Instances contain [numerator] and [denominator] represented as [Long]. - * - * Also [numerator] and [denominator] are coprime and [denominator] is positive. - * - * @author [Gleb Minaev](https://github.com/lounres) - */ -public class Rational: Comparable { - public companion object { - /** - * Constant containing the zero (the additive identity) of the [Rational] field. - */ - public val ZERO: Rational = Rational(I0) - /** - * Constant containing the one (the multiplicative identity) of the [Rational] field. - */ - public val ONE: Rational = Rational(I1) +class Rational { + companion object { + val ZERO: Rational = Rational(0L) + val ONE: Rational = Rational(1L) } - /** - * Numerator of the fraction. It's stored as non-negative coprime with [denominator] integer. - */ - public val numerator: BigInt - /** - * Denominator of the fraction. It's stored as non-zero coprime with [numerator] integer. - */ - public val denominator: BigInt + val numerator: Long + val denominator: Long - /** - * If [toCheckInput] is `true` before assigning values to [Rational.numerator] and [Rational.denominator] makes them coprime and makes - * denominator positive. Otherwise, just assigns the values. - * - * @throws ArithmeticException If denominator is zero. - */ - internal constructor(numerator: BigInt, denominator: BigInt, toCheckInput: Boolean = true) { + internal constructor(numerator: Long, denominator: Long, toCheckInput: Boolean = true) { if (toCheckInput) { - if (denominator == I0) throw ArithmeticException("/ by zero") + if (denominator == 0L) throw ArithmeticException("/ by zero") - val greatestCommonDivider = gcd(numerator, denominator).let { if (denominator < I0) -it else it } + val greatestCommonDivider = gcd(numerator, denominator).let { if (denominator < 0L) -it else it } this.numerator = numerator / greatestCommonDivider this.denominator = denominator / greatestCommonDivider @@ -63,303 +32,86 @@ public class Rational: Comparable { } } - /** - * Before assigning values to [Rational.numerator] and [Rational.denominator] makes them coprime and makes - * denominator positive. - * - * @throws ArithmeticException If denominator is zero. - */ - public constructor(numerator: BigInt, denominator: BigInt) : this(numerator, denominator, true) - public constructor(numerator: Int, denominator: BigInt) : this(numerator.toBigInt(), denominator, true) - public constructor(numerator: Long, denominator: BigInt) : this(numerator.toBigInt(), denominator, true) - public constructor(numerator: BigInt, denominator: Int) : this(numerator, denominator.toBigInt(), true) - public constructor(numerator: BigInt, denominator: Long) : this(numerator, denominator.toBigInt(), true) - public constructor(numerator: Int, denominator: Int) : this(numerator.toBigInt(), denominator.toBigInt(), true) - public constructor(numerator: Int, denominator: Long) : this(numerator.toBigInt(), denominator.toBigInt(), true) - public constructor(numerator: Long, denominator: Int) : this(numerator.toBigInt(), denominator.toBigInt(), true) - public constructor(numerator: Long, denominator: Long) : this(numerator.toBigInt(), denominator.toBigInt(), true) - public constructor(numerator: BigInt) : this(numerator, I1, false) - public constructor(numerator: Int) : this(numerator.toBigInt(), I1, false) - public constructor(numerator: Long) : this(numerator.toBigInt(), I1, false) + 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) - /** - * Returns the same instant. - */ - public operator fun unaryPlus(): Rational = this - - /** - * Returns negation of the instant of [Rational] field. - */ - public operator fun unaryMinus(): Rational = Rational(-this.numerator, this.denominator) - - /** - * Returns sum of the instants of [Rational] field. - */ - public operator fun plus(other: Rational): Rational = + operator fun unaryPlus(): Rational = this + operator fun unaryMinus(): Rational = Rational(-this.numerator, this.denominator) + operator fun plus(other: Rational): Rational = Rational( numerator * other.denominator + denominator * other.numerator, denominator * other.denominator ) - - /** - * Returns sum of the instants of [Rational] field. [other] is represented as [Rational]. - */ - public operator fun plus(other: BigInt): Rational = + operator fun plus(other: Int): Rational = + Rational( + numerator + denominator * other.toLong(), + denominator + ) + operator fun plus(other: Long): Rational = Rational( numerator + denominator * other, denominator ) - - /** - * Returns sum of the instants of [Rational] field. [other] is represented as [Rational]. - */ - public operator fun plus(other: Int): Rational = - Rational( - numerator + denominator * other.toBigInt(), - denominator - ) - - /** - * Returns sum of the instants of [Rational] field. [other] is represented as [Rational]. - */ - public operator fun plus(other: Long): Rational = - Rational( - numerator + denominator * other.toBigInt(), - denominator - ) - - /** - * Returns difference of the instants of [Rational] field. - */ - public operator fun minus(other: Rational): Rational = + operator fun minus(other: Rational): Rational = Rational( numerator * other.denominator - denominator * other.numerator, denominator * other.denominator ) - - /** - * Returns difference of the instants of [Rational] field. [other] is represented as [Rational]. - */ - public operator fun minus(other: BigInt): Rational = + operator fun minus(other: Int): Rational = + Rational( + numerator - denominator * other.toLong(), + denominator + ) + operator fun minus(other: Long): Rational = Rational( numerator - denominator * other, denominator ) - - /** - * Returns difference of the instants of [Rational] field. [other] is represented as [Rational]. - */ - public operator fun minus(other: Int): Rational = - Rational( - numerator - denominator * other.toBigInt(), - denominator - ) - - /** - * Returns difference of the instants of [Rational] field. [other] is represented as [Rational]. - */ - public operator fun minus(other: Long): Rational = - Rational( - numerator - denominator * other.toBigInt(), - denominator - ) - - /** - * Returns product of the instants of [Rational] field. - */ - public operator fun times(other: Rational): Rational = + operator fun times(other: Rational): Rational = Rational( numerator * other.numerator, denominator * other.denominator ) - - /** - * Returns product of the instants of [Rational] field. [other] is represented as [Rational]. - */ - public operator fun times(other: BigInt): Rational = + operator fun times(other: Int): Rational = + Rational( + numerator * other.toLong(), + denominator + ) + operator fun times(other: Long): Rational = Rational( numerator * other, denominator ) - - /** - * Returns product of the instants of [Rational] field. [other] is represented as [Rational]. - */ - public operator fun times(other: Int): Rational = - Rational( - numerator * other.toBigInt(), - denominator - ) - - /** - * Returns product of the instants of [Rational] field. [other] is represented as [Rational]. - */ - public operator fun times(other: Long): Rational = - Rational( - numerator * other.toBigInt(), - denominator - ) - - /** - * Returns quotient of the instants of [Rational] field. - * - * @throws ArithmeticException if [other] is the zero of the field it can't be a divisor. - */ - public operator fun div(other: Rational): Rational = + operator fun div(other: Rational): Rational = Rational( numerator * other.denominator, denominator * other.numerator ) - - /** - * Returns quotient of the instants of [Rational] field. [other] is represented as [Rational]. - * - * @throws ArithmeticException if [other] is the zero of the field it can't be a divisor. - */ - public operator fun div(other: BigInt): Rational = + operator fun div(other: Int): Rational = + Rational( + numerator, + denominator * other.toLong() + ) + operator fun div(other: Long): Rational = Rational( numerator, denominator * other ) - - /** - * Returns quotient of the instants of [Rational] field. [other] is represented as [Rational]. - * - * @throws ArithmeticException if [other] is the zero of the field it can't be a divisor. - */ - public operator fun div(other: Int): Rational = - Rational( - numerator, - denominator * other.toBigInt() - ) - - /** - * Returns quotient of the instants of [Rational] field. [other] is represented as [Rational]. - * - * @throws ArithmeticException if [other] is the zero of the field it can't be a divisor. - */ - public operator fun div(other: Long): Rational = - Rational( - numerator, - denominator * other.toBigInt() - ) - - /** - * Returns reminder from integral division. - * - * @throws ArithmeticException if [other] is the zero of the field it can't be a divisor. - */ - public operator fun rem(other: Rational): Rational = - Rational( - (numerator * other.denominator) % (denominator * other.numerator), - denominator * other.denominator - ) - - /** - * Returns reminder from integral division. - * - * @throws ArithmeticException if [other] is the zero of the field it can't be a divisor. - */ - public operator fun rem(other: BigInt): Rational = - Rational( - numerator % denominator * other, - denominator * other - ) - - /** - * Returns reminder from integral division. - * - * @throws ArithmeticException if [other] is the zero of the field it can't be a divisor. - */ - public operator fun rem(other: Int): Rational = - Rational( - numerator % denominator * other.toBigInt(), - denominator * other.toBigInt() - ) - - /** - * Returns reminder from integral division. - * - * @throws ArithmeticException if [other] is the zero of the field it can't be a divisor. - */ - public operator fun rem(other: Long): Rational = - Rational( - numerator % denominator * other.toBigInt(), - denominator * other.toBigInt() - ) - - /** - * Checks equality of the instance to [other]. - * - * [BigInt], [Int] and [Long] values are also checked as Rational ones. - */ override fun equals(other: Any?): Boolean = when (other) { is Rational -> numerator == other.numerator && denominator == other.denominator - is BigInt -> numerator == other && denominator == I1 - is Int -> numerator == other && denominator == I1 - is Long -> numerator == other && denominator == I1 + is Int -> numerator == other && denominator == 1L + is Long -> numerator == other && denominator == 1L else -> false } - /** - * Compares the instance to [other] as [Comparable.compareTo]. - * - * @see Comparable.compareTo - */ - override operator fun compareTo(other: Rational): Int = (numerator * other.denominator).compareTo(other.numerator * denominator) + override fun hashCode(): Int = 31 * numerator.hashCode() + denominator.hashCode() - /** - * Compares the instance to [other] as [Comparable.compareTo]. - * - * [Integer] values are also checked as Rational ones. - * - * @see Comparable.compareTo - */ - public operator fun compareTo(other: BigInt): Int = (numerator).compareTo(denominator * other) - - /** - * Compares the instance to [other] as [Comparable.compareTo]. - * - * [Int] values are also checked as Rational ones. - * - * @see Comparable.compareTo - */ - public operator fun compareTo(other: Int): Int = (numerator).compareTo(denominator * other.toBigInt()) - - /** - * Compares the instance to [other] as [Comparable.compareTo]. - * - * [Long] values are also checked as Rational ones. - * - * @see Comparable.compareTo - */ - public operator fun compareTo(other: Long): Int = (numerator).compareTo(denominator * other.toBigInt()) - - public override fun hashCode(): Int = 31 * numerator.hashCode() + denominator.hashCode() - -// /** Creates a range from this value to the specified [other] value. */ -// operator fun rangeTo(other: JBInt) = ClosedRationalRange(this, other.toRational()) -// /** Creates a range from this value to the specified [other] value. */ -// operator fun rangeTo(other: Rational) = ClosedRationalRange(this, other) -// /** Creates a range from this value to the specified [other] value. */ -// operator fun rangeTo(other: Int) = ClosedRationalRange(this, other.toRational()) -// /** Creates a range from this value to the specified [other] value. */ -// operator fun rangeTo(other: Long) = ClosedRationalRange(this, other.toRational()) - - public fun toRational(): Rational = this - - public fun toBigInt(): BigInt = numerator / denominator - -// public fun toInt(): Int = (numerator / denominator).toInt() -// -// public fun toLong(): Long = (numerator / denominator).toLong() -// -// public fun toDouble(): Double = (numerator.toDouble() / denominator.toDouble()) -// -// public fun toFloat(): Float = (numerator.toFloat() / denominator.toFloat()) - - public override fun toString(): String = if (denominator == I1) "$numerator" else "$numerator/$denominator" + override fun toString(): String = if (denominator == 1L) "$numerator" else "$numerator/$denominator" } @@ -368,7 +120,7 @@ public class Rational: Comparable { */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") @OptIn(UnstableKMathAPI::class) -public object RationalField : Field, NumbersAddOps { +object RationalField : Field, NumbersAddOps { override inline val zero: Rational get() = Rational.ZERO override inline val one: Rational get() = Rational.ONE diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/RationalWithMemorization.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/RationalWithMemorization.kt index 6aa5ecc09..05d9115fa 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/RationalWithMemorization.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/RationalWithMemorization.kt @@ -12,7 +12,7 @@ class RationalWithMemorization private constructor( val value: Rational, override val memory : OperationsMemory ): WithMemorization { - public companion object { + companion object { /** * Constant containing the zero (the additive identity) of the [Rational] field. */ @@ -22,48 +22,42 @@ class RationalWithMemorization private constructor( */ public val ONE: RationalWithMemorization = RationalWithMemorization(Rational.ONE, object : Endpoint {}) } - public constructor(numerator: BigInt, denominator: BigInt) : this(Rational(numerator, denominator), object : Endpoint {}) - public constructor(numerator: Int, denominator: BigInt) : this(Rational(numerator, denominator), object : Endpoint {}) - public constructor(numerator: Long, denominator: BigInt) : this(Rational(numerator, denominator), object : Endpoint {}) - public constructor(numerator: BigInt, denominator: Int) : this(Rational(numerator, denominator), object : Endpoint {}) - public constructor(numerator: BigInt, denominator: Long) : this(Rational(numerator, denominator), object : Endpoint {}) - public constructor(numerator: Int, denominator: Int) : this(Rational(numerator, denominator), object : Endpoint {}) - public constructor(numerator: Int, denominator: Long) : this(Rational(numerator, denominator), object : Endpoint {}) - public constructor(numerator: Long, denominator: Int) : this(Rational(numerator, denominator), object : Endpoint {}) - public constructor(numerator: Long, denominator: Long) : this(Rational(numerator, denominator), object : Endpoint {}) - public constructor(numerator: BigInt) : this(Rational(numerator), object : Endpoint {}) - public constructor(numerator: Int) : this(Rational(numerator), object : Endpoint {}) - public constructor(numerator: Long) : this(Rational(numerator), object : Endpoint {}) + constructor(numerator: Int, denominator: Int) : this(Rational(numerator, denominator), object : Endpoint {}) + constructor(numerator: Int, denominator: Long) : this(Rational(numerator, denominator), object : Endpoint {}) + constructor(numerator: Long, denominator: Int) : this(Rational(numerator, denominator), object : Endpoint {}) + constructor(numerator: Long, denominator: Long) : this(Rational(numerator, denominator), object : Endpoint {}) + constructor(numerator: Int) : this(Rational(numerator), object : Endpoint {}) + constructor(numerator: Long) : this(Rational(numerator), object : Endpoint {}) - public operator fun unaryPlus(): RationalWithMemorization = this - public operator fun unaryMinus(): RationalWithMemorization = RationalWithMemorization( + operator fun unaryPlus(): RationalWithMemorization = this + operator fun unaryMinus(): RationalWithMemorization = RationalWithMemorization( -value, object : Negation { override val negated: OperationsMemory = memory } ) - public operator fun plus(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization( + operator fun plus(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization( value + other.value, object : Sum { override val augend: OperationsMemory = memory override val addend: OperationsMemory = other.memory } ) - public operator fun minus(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization( + operator fun minus(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization( value - other.value, object : Difference { override val minuend: OperationsMemory = memory override val subtrahend: OperationsMemory = other.memory } ) - public operator fun times(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization( + operator fun times(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization( value * other.value, object : Product { override val multiplicand: OperationsMemory = memory override val multiplier: OperationsMemory = other.memory } ) - public operator fun div(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization( + operator fun div(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization( value / other.value, object : Quotient { override val dividend: OperationsMemory = memory @@ -71,16 +65,16 @@ class RationalWithMemorization private constructor( } ) - public override fun equals(other: Any?): Boolean = + override fun equals(other: Any?): Boolean = other is RationalWithMemorization && value == other.value - public override fun hashCode(): Int = value.hashCode() + override fun hashCode(): Int = value.hashCode() - public override fun toString(): String = value.toString() + override fun toString(): String = value.toString() } @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -public object RationalWithMemorizationRing : Ring { +object RationalWithMemorizationRing : Ring { override inline val zero: RationalWithMemorization get() = RationalWithMemorization.ZERO override inline val one: RationalWithMemorization get() = RationalWithMemorization.ONE @@ -94,7 +88,7 @@ public object RationalWithMemorizationRing : Ring { } @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -public object RationalWithMemorizationField : Field { +object RationalWithMemorizationField : Field { override inline val zero: RationalWithMemorization get() = RationalWithMemorization.ZERO override inline val one: RationalWithMemorization get() = RationalWithMemorization.ONE diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt index eab29842c..2eb421024 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt @@ -5,21 +5,8 @@ package space.kscience.kmath.test.misc -import space.kscience.kmath.operations.* -import space.kscience.kmath.operations.BigInt.Companion.ZERO as I0 +import kotlin.math.abs // TODO: Move to corresponding module "kmath-number-theory" -/** - * Computes [Greatest Common Divisor](https://en.wikipedia.org/wiki/Greatest_common_divisor) of [a] and [b]. - * - * It's computed by [Euclidean algorithm](https://en.wikipedia.org/wiki/Greatest_common_divisor#Euclidean_algorithm). - * Hence, its time complexity is $$O(\log(a+b))$$ (see [Wolfram MathWorld](https://mathworld.wolfram.com/EuclideanAlgorithm.html)). - */ -public tailrec fun gcd(a: BigInt, b: BigInt): BigInt = if (a == I0) abs(b) else gcd(b % a, a) - -/** - * Computes [Greatest Common Divisor](https://en.wikipedia.org/wiki/Greatest_common_divisor) of the [values]. - */ -public fun gcd(vararg values: BigInt): BigInt = values.reduce(::gcd) -public fun gcd(values: Iterable): BigInt = values.reduce(::gcd) \ No newline at end of file +tailrec fun gcd(a: Long, b: Long): Long = if (a == 0L) abs(b) else gcd(b % a, a) \ No newline at end of file -- 2.34.1 From 5d4514a742d0c36dabf2b0e03243f61381453313 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sat, 19 Mar 2022 19:35:41 +0300 Subject: [PATCH 047/275] More test tools! More tests!! More fixes of stupid bugs!!! :sob: --- .../kscience/kmath/functions/Polynomial.kt | 2 +- .../kmath/functions/PolynomialTest.kt | 224 +++++++++++++++++- .../kscience/kmath/test/misc/IntModulo.kt | 142 +++++++++++ .../kscience/kmath/test/misc/Rational.kt | 4 - .../space/kscience/kmath/test/misc/misc.kt | 25 +- 5 files changed, 387 insertions(+), 10 deletions(-) create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 722566f5d..9c1f9efae 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -220,7 +220,7 @@ public open class PolynomialSpace>( public override operator fun C.minus(other: Polynomial): Polynomial = if (this.isZero()) other else with(other.coefficients) { - if (isEmpty()) Polynomial(listOf(-this@minus)) + if (isEmpty()) Polynomial(listOf(this@minus)) else Polynomial( toMutableList() .apply { diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt index e2970d953..0bf34f198 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt @@ -6,11 +6,11 @@ package space.kscience.kmath.functions import space.kscience.kmath.operations.algebra -import space.kscience.kmath.test.misc.Rational -import space.kscience.kmath.test.misc.RationalField +import space.kscience.kmath.test.misc.* import kotlin.test.Test import kotlin.test.assertEquals + class PolynomialTest { @Test fun test_Polynomial_Int_plus() { @@ -93,6 +93,116 @@ class PolynomialTest { } } @Test + fun test_Polynomial_Int_times() { + IntModuloRing(35).polynomial { + assertEquals( + Polynomial(34, 2, 1, 20, 2), + Polynomial(22, 26, 13, 15, 26) * 27, + "test 1" + ) + assertEquals( + Polynomial(), + Polynomial(7, 0, 49, 21, 14) * 15, + "test 2" + ) + } + } + @Test + fun test_Int_Polynomial_plus() { + RationalField.polynomial { + assertEquals( + Polynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)), + -3 + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)), + "test 1" + ) + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + 2 + Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 2" + ) + assertEquals( + Polynomial(), + 2 + Polynomial(Rational(-2)), + "test 3" + ) + assertEquals( + Polynomial(), + 0 + Polynomial(), + "test 4" + ) + assertEquals( + Polynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), + 1 + Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 5" + ) + assertEquals( + Polynomial(Rational(-1)), + 1 + Polynomial(Rational(-2)), + "test 6" + ) + assertEquals( + Polynomial(Rational(2)), + 2 + Polynomial(), + "test 7" + ) + } + } + @Test + fun test_Int_Polynomial_minus() { + RationalField.polynomial { + assertEquals( + Polynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), + 3 - Polynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7)), + "test 1" + ) + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + -2 - Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 2" + ) + assertEquals( + Polynomial(), + -2 - Polynomial(Rational(-2)), + "test 3" + ) + assertEquals( + Polynomial(), + 0 - Polynomial(), + "test 4" + ) + assertEquals( + Polynomial(Rational(1), Rational(0), Rational(0), Rational(0)), + -1 - Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 5" + ) + assertEquals( + Polynomial(Rational(1)), + -1 - Polynomial(Rational(-2)), + "test 6" + ) + assertEquals( + Polynomial(Rational(-2)), + -2 - Polynomial(), + "test 7" + ) + } + } + @Test + fun test_Int_Polynomial_times() { + IntModuloRing(35).polynomial { + assertEquals( + Polynomial(34, 2, 1, 20, 2), + 27 * Polynomial(22, 26, 13, 15, 26), + "test 1" + ) + assertEquals( + Polynomial(), + 15 * Polynomial(7, 0, 49, 21, 14), + "test 2" + ) + } + } + @Test fun test_Polynomial_Constant_plus() { RationalField.polynomial { assertEquals( @@ -173,6 +283,116 @@ class PolynomialTest { } } @Test + fun test_Polynomial_Constant_times() { + IntModuloRing(35).polynomial { + assertEquals( + Polynomial(34, 2, 1, 20, 2), + Polynomial(22, 26, 13, 15, 26) * number(27), + "test 1" + ) + assertEquals( + Polynomial(), + Polynomial(7, 0, 49, 21, 14) * number(15), + "test 2" + ) + } + } + @Test + fun test_Constant_Polynomial_plus() { + RationalField.polynomial { + assertEquals( + Polynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)), + Rational(-3) + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)), + "test 1" + ) + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + Rational(2) + Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 2" + ) + assertEquals( + Polynomial(), + Rational(2) + Polynomial(Rational(-2)), + "test 3" + ) + assertEquals( + Polynomial(), + Rational(0) + Polynomial(), + "test 4" + ) + assertEquals( + Polynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), + Rational(1) + Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 5" + ) + assertEquals( + Polynomial(Rational(-1)), + Rational(1) + Polynomial(Rational(-2)), + "test 6" + ) + assertEquals( + Polynomial(Rational(2)), + Rational(2) + Polynomial(), + "test 7" + ) + } + } + @Test + fun test_Constant_Polynomial_minus() { + RationalField.polynomial { + assertEquals( + Polynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), + Rational(3) - Polynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7)), + "test 1" + ) + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + Rational(-2) - Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 2" + ) + assertEquals( + Polynomial(), + Rational(-2) - Polynomial(Rational(-2)), + "test 3" + ) + assertEquals( + Polynomial(), + Rational(0) - Polynomial(), + "test 4" + ) + assertEquals( + Polynomial(Rational(1), Rational(0), Rational(0), Rational(0)), + Rational(-1) - Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 5" + ) + assertEquals( + Polynomial(Rational(1)), + Rational(-1) - Polynomial(Rational(-2)), + "test 6" + ) + assertEquals( + Polynomial(Rational(-2)), + Rational(-2) - Polynomial(), + "test 7" + ) + } + } + @Test + fun test_Constant_Polynomial_times() { + IntModuloRing(35).polynomial { + assertEquals( + Polynomial(34, 2, 1, 20, 2), + 27 * Polynomial(22, 26, 13, 15, 26), + "test 1" + ) + assertEquals( + Polynomial(), + 15 * Polynomial(7, 0, 49, 21, 14), + "test 2" + ) + } + } + @Test fun test_Polynomial_Polynomial_plus() { RationalField.polynomial { // (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 diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt new file mode 100644 index 000000000..a8a8a09bc --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt @@ -0,0 +1,142 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.test.misc + +import space.kscience.kmath.functions.Polynomial +import space.kscience.kmath.functions.PolynomialSpace +import space.kscience.kmath.misc.UnstableKMathAPI +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(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", "NOTHING_TO_INLINE") +@OptIn(UnstableKMathAPI::class) +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(0, modulus, toCheckInput = false) + + fun number(arg: Int) = 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 +} + +fun PolynomialSpace.number(arg: Int) = IntModulo(arg, ring.modulus, toCheckInput = false) + +fun PolynomialSpace.Polynomial(vararg coefs: Int): Polynomial = + Polynomial(coefs.map { IntModulo(it, ring.modulus) }) +fun IntModuloRing.Polynomial(vararg coefs: Int): Polynomial = + Polynomial(coefs.map { IntModulo(it, modulus) }) \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt index 842e354db..72bb5942c 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt @@ -114,10 +114,6 @@ class Rational { override fun toString(): String = if (denominator == 1L) "$numerator" else "$numerator/$denominator" } - -/** - * Algebraic structure for rational numbers. - */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") @OptIn(UnstableKMathAPI::class) object RationalField : Field, NumbersAddOps { diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt index 2eb421024..cc647fa2c 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt @@ -5,8 +5,27 @@ package space.kscience.kmath.test.misc -import kotlin.math.abs - // TODO: Move to corresponding module "kmath-number-theory" -tailrec fun gcd(a: Long, b: Long): Long = if (a == 0L) abs(b) else gcd(b % a, a) \ No newline at end of file +import kotlin.math.abs + + +data class BezoutIdentityWithGCD(val first: T, val second: T, val gcd: T) + +tailrec fun gcd(a: Long, b: Long): Long = if (a == 0L) abs(b) else gcd(b % a, a) + +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 -- 2.34.1 From fbc21101bbcb2cbc9a383fa2c18d635cba72c25e Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sun, 20 Mar 2022 06:26:52 +0300 Subject: [PATCH 048/275] Added test. Fixed isOne and isMinusOne for Polynomial. --- .../kscience/kmath/functions/Polynomial.kt | 6 +- .../kmath/functions/PolynomialTest.kt | 86 ++++++++++++++++--- .../kmath/functions/PolynomialUtilTest.kt | 27 ++++++ 3 files changed, 104 insertions(+), 15 deletions(-) create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 9c1f9efae..7e0f6f62d 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -369,14 +369,14 @@ public open class PolynomialSpace>( */ public override fun Polynomial.isOne(): Boolean = with(coefficients) { - isNotEmpty() && withIndex().any { (index, c) -> if (index == 0) c.isOne() else c.isZero() } + isNotEmpty() && withIndex().all { (index, c) -> if (index == 0) c.isOne() else c.isZero() } } /** * Check if the instant is minus unit polynomial. */ public override fun Polynomial.isMinusOne(): Boolean = with(coefficients) { - isNotEmpty() && withIndex().any { (index, c) -> if (index == 0) c.isMinusOne() else c.isZero() } + isNotEmpty() && withIndex().all { (index, c) -> if (index == 0) c.isMinusOne() else c.isZero() } } /** @@ -415,7 +415,7 @@ public open class PolynomialSpace>( with(coefficients) { when { isEmpty() -> constantZero - degree > 0 -> null + withIndex().any { (index, c) -> index == 0 || c.isZero() } -> null else -> first() } } diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt index 0bf34f198..85b309467 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt @@ -5,10 +5,8 @@ package space.kscience.kmath.functions -import space.kscience.kmath.operations.algebra import space.kscience.kmath.test.misc.* -import kotlin.test.Test -import kotlin.test.assertEquals +import kotlin.test.* class PolynomialTest { @@ -393,6 +391,21 @@ class PolynomialTest { } } @Test + fun test_Polynomial_unaryMinus() { + RationalField.polynomial { + assertEquals( + Polynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7)), + -Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)), + "test 1" + ) + assertEquals( + Polynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7), Rational(0), Rational(0)), + -Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7), Rational(0), Rational(0)), + "test 2" + ) + } + } + @Test fun test_Polynomial_Polynomial_plus() { RationalField.polynomial { // (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 @@ -459,17 +472,66 @@ class PolynomialTest { } } @Test - fun simple_polynomial_test() { - val polynomial : Polynomial - Double.algebra.scalablePolynomial { - val x = Polynomial(listOf(0.0, 1.0)) - polynomial = x * x - 2 * x + 1 + fun test_Polynomial_Polynomial_times() { + IntModuloRing(35).polynomial { + // (1 + x + x^2) * (1 - x + x^2) ?= 1 + x^2 + x^4 + assertEquals( + Polynomial(1, 0, 1, 0, 1), + Polynomial(1, -1, 1) * Polynomial(1, 1, 1), + "test 1" + ) + // Spoiler: 5 * 7 = 0 + assertEquals( + Polynomial(), + Polynomial(5, -25, 10) * Polynomial(21, 14, -7), + "test 2" + ) } - assertEquals(0.0, polynomial.substitute(1.0), 0.001) } @Test - fun testIntegration() { - val polynomial = Polynomial(1.0, -2.0, 1.0) - assertEquals(0.0, polynomial.substitute(1.0), 0.001) + fun test_Polynomial_isZero() { + RationalField.polynomial { + assertTrue("test 1") { Polynomial().isZero() } + assertTrue("test 2") { Polynomial(Rational(0)).isZero() } + assertTrue("test 3") { Polynomial(Rational(0), Rational(0)).isZero() } + assertTrue("test 4") { Polynomial(Rational(0), Rational(0), Rational(0)).isZero() } + assertFalse("test 5") { Polynomial(Rational(3, 5)).isZero() } + assertFalse("test 6") { Polynomial(Rational(3, 5), Rational(0)).isZero() } + assertFalse("test 7") { Polynomial(Rational(0), Rational(3, 5), Rational(0)).isZero() } + } + } + @Test + fun test_Polynomial_isOne() { + RationalField.polynomial { + assertFalse("test 1") { Polynomial().isOne() } + assertFalse("test 2") { Polynomial(Rational(0)).isOne() } + assertFalse("test 3") { Polynomial(Rational(0), Rational(0)).isOne() } + assertFalse("test 4") { Polynomial(Rational(0), Rational(0), Rational(0)).isOne() } + assertFalse("test 5") { Polynomial(Rational(3, 5)).isOne() } + assertTrue("test 6") { Polynomial(Rational(5, 5)).isOne() } + assertFalse("test 7") { Polynomial(Rational(3, 5), Rational(0)).isOne() } + assertTrue("test 8") { Polynomial(Rational(3, 3), Rational(0)).isOne() } + assertFalse("test 9") { Polynomial(Rational(0), Rational(3, 5), Rational(0)).isOne() } + assertFalse("test 10") { Polynomial(Rational(0), Rational(5, 5), Rational(0)).isOne() } + assertFalse("test 11") { Polynomial(Rational(1), Rational(3, 5), Rational(0)).isOne() } + assertFalse("test 12") { Polynomial(Rational(1), Rational(5, 5), Rational(0)).isOne() } + } + } + @Test + fun test_Polynomial_isMinusOne() { + RationalField.polynomial { + assertFalse("test 1") { Polynomial().isMinusOne() } + assertFalse("test 2") { Polynomial(Rational(0)).isMinusOne() } + assertFalse("test 3") { Polynomial(Rational(0), Rational(0)).isMinusOne() } + assertFalse("test 4") { Polynomial(Rational(0), Rational(0), Rational(0)).isMinusOne() } + assertFalse("test 5") { Polynomial(Rational(3, 5)).isMinusOne() } + assertTrue("test 6") { Polynomial(Rational(-5, 5)).isMinusOne() } + assertFalse("test 7") { Polynomial(Rational(3, 5), Rational(0)).isMinusOne() } + assertTrue("test 8") { Polynomial(Rational(-3, 3), Rational(0)).isMinusOne() } + assertFalse("test 9") { Polynomial(Rational(0), Rational(3, 5), Rational(0)).isMinusOne() } + assertFalse("test 10") { Polynomial(Rational(0), Rational(5, -5), Rational(0)).isMinusOne() } + assertFalse("test 11") { Polynomial(Rational(-1), Rational(3, 5), Rational(0)).isMinusOne() } + assertFalse("test 12") { Polynomial(Rational(-1), Rational(5, -5), Rational(0)).isMinusOne() } + } } } \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt new file mode 100644 index 000000000..b9dd74800 --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.algebra +import kotlin.test.Test +import kotlin.test.assertEquals + +class PolynomialUtilTest { + @Test + fun simple_polynomial_test() { + val polynomial : Polynomial + Double.algebra.scalablePolynomial { + val x = Polynomial(listOf(0.0, 1.0)) + polynomial = x * x - 2 * x + 1 + } + assertEquals(0.0, polynomial.substitute(1.0), 0.001) + } + @Test + fun testIntegration() { + val polynomial = Polynomial(1.0, -2.0, 1.0) + assertEquals(0.0, polynomial.substitute(1.0), 0.001) + } +} \ No newline at end of file -- 2.34.1 From 25ec59b9851e71e3a652e043002a50902e8479b4 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sun, 20 Mar 2022 23:22:39 +0300 Subject: [PATCH 049/275] Finished with tests for Polynomial. --- .../kscience/kmath/functions/Polynomial.kt | 17 +- .../kmath/functions/polynomialUtil.kt | 50 ++-- .../kmath/functions/PolynomialTest.kt | 154 ++++++++++++ .../kmath/functions/PolynomialUtilTest.kt | 223 +++++++++++++++++- 4 files changed, 407 insertions(+), 37 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 7e0f6f62d..d6c959fd1 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -386,7 +386,7 @@ public open class PolynomialSpace>( /** * Instance of unit constant (unit of the underlying ring). */ - override val one: Polynomial = Polynomial(listOf(constantZero)) + override val one: Polynomial = Polynomial(listOf(constantOne)) /** * Checks equality of the polynomials. @@ -394,11 +394,8 @@ public open class PolynomialSpace>( public override infix fun Polynomial.equalsTo(other: Polynomial): Boolean = when { this === other -> true - else -> { - if (this.degree == other.degree) - (0..degree).all { coefficients[it] == other.coefficients[it] } - else false - } + this.degree == other.degree -> (0..degree).all { coefficients[it] == other.coefficients[it] } + else -> false } /** @@ -415,8 +412,8 @@ public open class PolynomialSpace>( with(coefficients) { when { isEmpty() -> constantZero - withIndex().any { (index, c) -> index == 0 || c.isZero() } -> null - else -> first() + withIndex().all { (index, c) -> index == 0 || c.isZero() } -> first() + else -> null } } @@ -489,8 +486,6 @@ public open class PolynomialSpace>( public class ScalablePolynomialSpace( ring: A, ) : PolynomialSpace(ring), ScaleOperations> where A : Ring, A : ScaleOperations { - override fun scale(a: Polynomial, value: Double): Polynomial = - ring { Polynomial(List(a.coefficients.size) { index -> a.coefficients[index] * value }) } - + ring { Polynomial(a.coefficients.map { scale(it, value) }) } } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt index 84c8d2e88..afaf27a52 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt @@ -127,9 +127,10 @@ public fun Polynomial.substitute(ring: Ring, arg: Polynomial) : Pol if (argDegree == -1) return coefficients[0].asPolynomial() val constantZero = zero val resultCoefs: MutableList = MutableList(thisDegree * argDegree + 1) { constantZero } + resultCoefs[0] = coefficients[thisDegree] val resultCoefsUpdate: MutableList = MutableList(thisDegree * argDegree + 1) { constantZero } var resultDegree = 0 - for (deg in thisDegree downTo 0) { + for (deg in thisDegree - 1 downTo 0) { resultCoefsUpdate[0] = coefficients[deg] multiplyAddingToUpdater( ring = ring, @@ -142,6 +143,8 @@ public fun Polynomial.substitute(ring: Ring, arg: Polynomial) : Pol ) resultDegree += argDegree } + + with(resultCoefs) { while (isNotEmpty() && elementAt(lastIndex) == constantZero) removeAt(lastIndex) } return Polynomial(resultCoefs) } @@ -162,7 +165,12 @@ public fun > Polynomial.asPolynomialFunctionOver(ring: A): (Po public fun Polynomial.derivative( algebra: A, ): Polynomial where A : Ring, A : NumericAlgebra = algebra { - Polynomial(coefficients.drop(1).mapIndexed { index, c -> number(index + 1) * c }) + Polynomial( + buildList(max(0, coefficients.size - 1)) { + for (deg in 1 .. coefficients.lastIndex) add(number(deg) * coefficients[deg]) + while (isNotEmpty() && elementAt(lastIndex) == algebra.zero) removeAt(lastIndex) + } + ) } /** @@ -171,9 +179,16 @@ public fun Polynomial.derivative( @UnstableKMathAPI public fun Polynomial.nthDerivative( algebra: A, - order: UInt, + order: Int, ): Polynomial where A : Ring, A : NumericAlgebra = algebra { - Polynomial(coefficients.drop(order.toInt()).mapIndexed { index, c -> (index + 1..index + order.toInt()).fold(c) { acc, i -> acc * number(i) } }) + require(order >= 0) { "Order of derivative must be non-negative" } + Polynomial( + 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) }) + while (isNotEmpty() && elementAt(lastIndex) == algebra.zero) removeAt(lastIndex) + } + ) } /** @@ -183,11 +198,13 @@ public fun Polynomial.nthDerivative( public fun Polynomial.antiderivative( algebra: A, ): Polynomial where A : Field, A : NumericAlgebra = algebra { - val integratedCoefficients = buildList(coefficients.size + 1) { - add(zero) - coefficients.mapIndexedTo(this) { index, t -> t / number(index + 1) } - } - Polynomial(integratedCoefficients) + Polynomial( + buildList(coefficients.size + 1) { + add(zero) + coefficients.mapIndexedTo(this) { index, t -> t / number(index + 1) } + while (isNotEmpty() && elementAt(lastIndex) == algebra.zero) removeAt(lastIndex) + } + ) } /** @@ -196,13 +213,16 @@ public fun Polynomial.antiderivative( @UnstableKMathAPI public fun Polynomial.nthAntiderivative( algebra: A, - order: UInt, + order: Int, ): Polynomial where A : Field, A : NumericAlgebra = algebra { - val newCoefficients = buildList(coefficients.size + order.toInt()) { - repeat(order.toInt()) { add(zero) } - coefficients.mapIndexedTo(this) { index, c -> (1..order.toInt()).fold(c) { acc, i -> acc / number(index + i) } } - } - return Polynomial(newCoefficients) + require(order >= 0) { "Order of antiderivative must be non-negative" } + Polynomial( + buildList(coefficients.size + order) { + repeat(order) { add(zero) } + coefficients.mapIndexedTo(this) { index, c -> (1..order).fold(c) { acc, i -> acc / number(index + i) } } + while (isNotEmpty() && elementAt(lastIndex) == algebra.zero) removeAt(lastIndex) + } + ) } /** diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt index 85b309467..141bdd436 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt @@ -534,4 +534,158 @@ class PolynomialTest { assertFalse("test 12") { Polynomial(Rational(-1), Rational(5, -5), Rational(0)).isMinusOne() } } } + @Test + fun test_Polynomial_equalsTo() { + RationalField.polynomial { + assertTrue("test 1") { + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) equalsTo + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + } + assertTrue("test 2") { + Polynomial(Rational(5, 9), Rational(0), Rational(-8, 7)) equalsTo + Polynomial(Rational(5, 9), Rational(0), Rational(-8, 7)) + } + assertTrue("test 3") { + Polynomial(Rational(0), Rational(0), Rational(-8, 7), Rational(0), Rational(0)) equalsTo + Polynomial(Rational(0), Rational(0), Rational(-8, 7)) + } + assertFalse("test 4") { + Polynomial(Rational(5, 9), Rational(5, 7), Rational(-8, 7)) equalsTo + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + } + assertFalse("test 5") { + Polynomial(Rational(8, 3), Rational(0), Rational(-8, 7)) equalsTo + Polynomial(Rational(5, 9), Rational(0), Rational(-8, 7)) + } + assertFalse("test 6") { + Polynomial(Rational(0), Rational(0), Rational(-8, 7), Rational(0), Rational(0)) equalsTo + Polynomial(Rational(0), Rational(0), Rational(8, 7)) + } + } + } + @Test + fun test_Polynomial_degree() { + RationalField.polynomial { + assertEquals( + 2, + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)).degree, + "test 1" + ) + assertEquals( + -1, + Polynomial().degree, + "test 2" + ) + assertEquals( + -1, + Polynomial(Rational(0)).degree, + "test 3" + ) + assertEquals( + -1, + Polynomial(Rational(0), Rational(0)).degree, + "test 4" + ) + assertEquals( + -1, + Polynomial(Rational(0), Rational(0), Rational(0)).degree, + "test 5" + ) + assertEquals( + 0, + Polynomial(Rational(5, 9)).degree, + "test 6" + ) + assertEquals( + 0, + Polynomial(Rational(5, 9), Rational(0)).degree, + "test 7" + ) + assertEquals( + 0, + Polynomial(Rational(5, 9), Rational(0), Rational(0)).degree, + "test 8" + ) + assertEquals( + 2, + Polynomial(Rational(0), Rational(0), Rational(-8, 7)).degree, + "test 9" + ) + assertEquals( + 2, + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7), Rational(0), Rational(0)).degree, + "test 10" + ) + assertEquals( + 2, + Polynomial(Rational(0), Rational(0), Rational(-8, 7), Rational(0), Rational(0)).degree, + "test 11" + ) + } + } + @Test + fun test_Polynomial_asConstantOrNull() { + RationalField.polynomial { + assertEquals( + Rational(0), + Polynomial().asConstantOrNull(), + "test 1" + ) + assertEquals( + Rational(0), + Polynomial(Rational(0)).asConstantOrNull(), + "test 2" + ) + assertEquals( + Rational(0), + Polynomial(Rational(0), Rational(0)).asConstantOrNull(), + "test 3" + ) + assertEquals( + Rational(0), + Polynomial(Rational(0), Rational(0), Rational(0)).asConstantOrNull(), + "test 4" + ) + assertEquals( + Rational(-7, 9), + Polynomial(Rational(-7, 9)).asConstantOrNull(), + "test 5" + ) + assertEquals( + Rational(-7, 9), + Polynomial(Rational(-7, 9), Rational(0)).asConstantOrNull(), + "test 6" + ) + assertEquals( + Rational(-7, 9), + Polynomial(Rational(-7, 9), Rational(0), Rational(0)).asConstantOrNull(), + "test 7" + ) + assertEquals( + null, + Polynomial(Rational(0), Rational(-7, 9)).asConstantOrNull(), + "test 8" + ) + assertEquals( + null, + Polynomial(Rational(0), Rational(-7, 9), Rational(0)).asConstantOrNull(), + "test 9" + ) + assertEquals( + null, + Polynomial(Rational(0), Rational(0), Rational(-7, 9)).asConstantOrNull(), + "test 10" + ) + assertEquals( + null, + Polynomial(Rational(4, 15), Rational(0), Rational(-7, 9)).asConstantOrNull(), + "test 11" + ) + assertEquals( + null, + Polynomial(Rational(4, 15), Rational(0), Rational(-7, 9), Rational(0)).asConstantOrNull(), + "test 12" + ) + } + } } \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt index b9dd74800..fbae61ed1 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt @@ -5,23 +5,224 @@ package space.kscience.kmath.functions -import space.kscience.kmath.operations.algebra +import space.kscience.kmath.test.misc.Rational +import space.kscience.kmath.test.misc.RationalField import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertFailsWith class PolynomialUtilTest { @Test - fun simple_polynomial_test() { - val polynomial : Polynomial - Double.algebra.scalablePolynomial { - val x = Polynomial(listOf(0.0, 1.0)) - polynomial = x * x - 2 * x + 1 - } - assertEquals(0.0, polynomial.substitute(1.0), 0.001) - } - @Test - fun testIntegration() { + fun test_substitute_Double() { val polynomial = Polynomial(1.0, -2.0, 1.0) assertEquals(0.0, polynomial.substitute(1.0), 0.001) } + @Test + fun test_substitute_Constant() { + assertEquals( + Rational(0), + Polynomial(Rational(1), Rational(-2), Rational(1)).substitute(RationalField, Rational(1)), + "test 1" + ) + assertEquals( + Rational(25057, 21000), + Polynomial(Rational(5,8), Rational(8, 3), Rational(4, 7), Rational(3, 2)) + .substitute(RationalField, Rational(1, 5)), + "test 2" + ) + assertEquals( + Rational(2983, 5250), + Polynomial(Rational(0), Rational(8, 3), Rational(4, 7), Rational(3, 2)) + .substitute(RationalField, Rational(1, 5)), + "test 3" + ) + assertEquals( + Rational(4961, 4200), + Polynomial(Rational(5,8), Rational(8, 3), Rational(4, 7), Rational(0)) + .substitute(RationalField, Rational(1, 5)), + "test 4" + ) + assertEquals( + Rational(3511, 3000), + Polynomial(Rational(5,8), Rational(8, 3), Rational(0), Rational(3, 2)) + .substitute(RationalField, Rational(1, 5)), + "test 5" + ) + } + @Test + fun test_substitute_Polynomial() { + assertEquals( + Polynomial(), + Polynomial(Rational(1), Rational(-2), Rational(1)).substitute(RationalField, Polynomial(Rational(1))), + "test 1" + ) + assertEquals( + Polynomial(Rational(709, 378), Rational(155, 252), Rational(19, 525), Rational(2, 875)), + Polynomial(Rational(1, 7), Rational(9, 4), Rational(1, 3), Rational(2, 7)) + .substitute(RationalField, Polynomial(Rational(6, 9), Rational(1, 5))), + "test 2" + ) + assertEquals( + Polynomial(Rational(655, 378), Rational(155, 252), Rational(19, 525), Rational(2, 875)), + Polynomial(Rational(0), Rational(9, 4), Rational(1, 3), Rational(2, 7)) + .substitute(RationalField, Polynomial(Rational(6, 9), Rational(1, 5))), + "test 3" + ) + assertEquals( + Polynomial(Rational(677, 378), Rational(97, 180), Rational(1, 75)), + Polynomial(Rational(1, 7), Rational(9, 4), Rational(1, 3), Rational(0)) + .substitute(RationalField, Polynomial(Rational(6, 9), Rational(1, 5))), + "test 4" + ) + assertEquals( + Polynomial(Rational(653, 378), Rational(221, 420), Rational(4, 175), Rational(2, 875)), + Polynomial(Rational(1, 7), Rational(9, 4), Rational(0), Rational(2, 7)) + .substitute(RationalField, Polynomial(Rational(6, 9), Rational(1, 5))), + "test 5" + ) + assertEquals( + Polynomial(Rational(89, 54)), + Polynomial(Rational(0), Rational(9, 4), Rational(1, 3), Rational(0)) + .substitute(RationalField, Polynomial(Rational(6, 9), Rational(0))), + "test 6" + ) + } + @Test + fun test_derivative() { + assertEquals( + Polynomial(Rational(-2), Rational(2)), + Polynomial(Rational(1), Rational(-2), Rational(1)).derivative(RationalField), + "test 1" + ) + assertEquals( + Polynomial(Rational(-8, 3), Rational(8, 9), Rational(15, 7), Rational(-20, 9)), + Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).derivative(RationalField), + "test 2" + ) + assertEquals( + Polynomial(Rational(0), Rational(8, 9), Rational(15, 7), Rational(-20, 9)), + Polynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).derivative(RationalField), + "test 3" + ) + assertEquals( + Polynomial(Rational(-8, 3), Rational(8, 9), Rational(15, 7)), + Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).derivative(RationalField), + "test 4" + ) + } + @Test + fun test_nthDerivative() { + assertEquals( + Polynomial(Rational(-2), Rational(2)), + Polynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, 1), + "test 1" + ) + assertFailsWith("test2") { + Polynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, -1) + } + assertEquals( + Polynomial(Rational(1), Rational(-2), Rational(1)), + Polynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, 0), + "test 3" + ) + assertEquals( + Polynomial(Rational(2)), + Polynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, 2), + "test 4" + ) + assertEquals( + Polynomial(), + Polynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, 3), + "test 5" + ) + assertEquals( + Polynomial(), + Polynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, 4), + "test 6" + ) + assertEquals( + Polynomial(Rational(8, 9), Rational(30, 7), Rational(-20, 3)), + Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).nthDerivative(RationalField, 2), + "test 7" + ) + assertEquals( + Polynomial(Rational(8, 9), Rational(30, 7), Rational(-20, 3)), + Polynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).nthDerivative(RationalField, 2), + "test 8" + ) + assertEquals( + Polynomial(Rational(8, 9), Rational(30, 7)), + Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).nthDerivative(RationalField, 2), + "test 9" + ) + } + @Test + fun test_antiderivative() { + assertEquals( + Polynomial(Rational(0), Rational(1), Rational(-1), Rational(1, 3)), + Polynomial(Rational(1), Rational(-2), Rational(1)).antiderivative(RationalField), + "test 1" + ) + assertEquals( + Polynomial(Rational(0), Rational(1, 5), Rational(-4, 3), Rational(4, 27), Rational(5, 28), Rational(-1, 9)), + Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).antiderivative(RationalField), + "test 2" + ) + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0), Rational(4, 27), Rational(5, 28), Rational(-1, 9)), + Polynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).antiderivative(RationalField), + "test 3" + ) + assertEquals( + Polynomial(Rational(0), Rational(1, 5), Rational(-4, 3), Rational(4, 27), Rational(5, 28)), + Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).antiderivative(RationalField), + "test 4" + ) + } + @Test + fun test_nthAntiderivative() { + assertEquals( + Polynomial(Rational(0), Rational(1), Rational(-1), Rational(1, 3)), + Polynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, 1), + "test 1" + ) + assertFailsWith("test2") { + Polynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, -1) + } + assertEquals( + Polynomial(Rational(1), Rational(-2), Rational(1)), + Polynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, 0), + "test 3" + ) + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(1, 2), Rational(-1, 3), Rational(1, 12)), + Polynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, 2), + "test 4" + ) + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0), Rational(1, 6), Rational(-1, 12), Rational(1, 60)), + Polynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, 3), + "test 5" + ) + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0), Rational(0), Rational(1, 24), Rational(-1, 60), Rational(1, 360)), + Polynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, 4), + "test 6" + ) + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(1, 10), Rational(-4, 9), Rational(1, 27), Rational(1, 28), Rational(-1, 54)), + Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).nthAntiderivative(RationalField, 2), + "test 7" + ) + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0), Rational(0), Rational(1, 27), Rational(1, 28), Rational(-1, 54)), + Polynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).nthAntiderivative(RationalField, 2), + "test 8" + ) + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(1, 10), Rational(-4, 9), Rational(1, 27), Rational(1, 28)), + Polynomial(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 -- 2.34.1 From 88e0dcf413d518e571118eb5d1bf3310110bad5c Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Mon, 21 Mar 2022 18:26:09 +0300 Subject: [PATCH 050/275] Added usage of more correct exceptions. --- .../kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt | 2 +- .../space/kscience/kmath/functions/AbstractRationalFunction.kt | 2 +- .../kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt index aacf055fa..fd1b51fae 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt @@ -295,7 +295,7 @@ public interface AbstractPolynomialSpace> : Ring

* If polynomial is a constant polynomial represents and returns it as constant. * Otherwise, (when the polynomial is not constant polynomial) raises corresponding exception. */ - public fun P.asConstant(): C = asConstantOrNull() ?: error("Can not represent non-constant polynomial as a constant") + public fun P.asConstant(): C = requireNotNull(asConstantOrNull()) { "Can not represent non-constant polynomial as a constant" } override fun add(left: P, right: P): P = left + right override fun multiply(left: P, right: P): P = left * right diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt index b9ca01da4..cdc4bf530 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt @@ -460,7 +460,7 @@ public interface AbstractRationalFunctionalSpace, R: * If polynomial is a constant polynomial represents and returns it as constant. * Otherwise, (when the polynomial is not constant polynomial) raises corresponding exception. */ - public fun P.asConstant(): C = asConstantOrNull() ?: error("Can not represent non-constant polynomial as a constant") + public fun P.asConstant(): C = requireNotNull(asConstantOrNull()) { "Can not represent non-constant polynomial as a constant" } /** * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt index fbae61ed1..21c5436d3 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt @@ -11,6 +11,7 @@ import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFailsWith + class PolynomialUtilTest { @Test fun test_substitute_Double() { -- 2.34.1 From 83d57c7295a7b79a9991417c8ede01efc935a54d Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Mon, 21 Mar 2022 21:22:25 +0300 Subject: [PATCH 051/275] Added RFs' interface to remove another boilerplate. Fixed bug in RFs' equalsTo. --- .../functions/AbstractRationalFunction.kt | 228 +++++++++++++++++- .../functions/LabeledRationalFunction.kt | 216 ++--------------- .../functions/NumberedRationalFunction.kt | 216 ++--------------- .../kmath/functions/RationalFunction.kt | 221 ++--------------- 4 files changed, 277 insertions(+), 604 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt index cdc4bf530..7feab3dfb 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt @@ -423,7 +423,13 @@ public interface AbstractRationalFunctionalSpace, R: /** * Checks equality of the rational functions. */ - public infix fun R.equalsTo(other: R): Boolean + public infix fun R.equalsTo(other: R): Boolean = + when { + this === other -> true + numerator.isZero() != other.numerator.isZero() -> false + numeratorDegree - denominatorDegree != with(other) { numeratorDegree - denominatorDegree } -> false + else -> numerator * other.denominator equalsTo other.numerator * denominator + } /** * Checks NOT equality of the polynomials. */ @@ -857,4 +863,224 @@ public interface AbstractRationalFunctionalSpaceOverPolynomialSpace< * Otherwise, (when the polynomial is not constant polynomial) raises corresponding exception. */ public override fun P.asConstant(): C = polynomialRing { this@asConstant.asConstant() } +} + +/** + * 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. + */ // TODO: Add support of field +@Suppress("INAPPLICABLE_JVM_NAME") +public abstract class AbstractPolynomialFractionsSpace< + C, + P: AbstractPolynomial, + R: AbstractRationalFunction, + > : AbstractRationalFunctionalSpace { + protected abstract fun constructRationalFunction(numerator: P, denominator: P) : R + + /** + * Returns sum of the rational function and the integer represented as 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 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 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 sum of the integer represented as 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 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 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 sum of the constant represented as rational function and the rational function. + */ + public override operator fun C.plus(other: R): R = + constructRationalFunction( + other.denominator * this + other.numerator, + other.denominator + ) + /** + * Returns difference between the constant represented as polynomial and the rational function. + */ + public override operator fun C.minus(other: R): R = + constructRationalFunction( + other.denominator * this - other.numerator, + other.denominator + ) + /** + * Returns product of the constant represented as polynomial and the rational function. + */ + public override operator fun C.times(other: R): R = + constructRationalFunction( + this * other.numerator, + other.denominator + ) + + /** + * Returns sum of the constant represented as rational function and the rational function. + */ + public override operator fun R.plus(other: C): R = + constructRationalFunction( + numerator + denominator * other, + denominator + ) + /** + * Returns difference between the constant represented as rational function and the rational function. + */ + public override operator fun R.minus(other: C): R = + constructRationalFunction( + numerator - denominator * other, + denominator + ) + /** + * Returns product of the constant represented as rational function and the rational function. + */ + public override operator fun R.times(other: C): R = + constructRationalFunction( + numerator * other, + denominator + ) + + /** + * Returns sum of the polynomial represented as rational function and the rational function. + */ + public override operator fun P.plus(other: R): R = + constructRationalFunction( + other.denominator * this + other.numerator, + other.denominator + ) + /** + * Returns difference between the polynomial represented as polynomial and the rational function. + */ + public override operator fun P.minus(other: R): R = + constructRationalFunction( + other.denominator * this - other.numerator, + other.denominator + ) + /** + * Returns product of the polynomial represented as polynomial and the rational function. + */ + public override operator fun P.times(other: R): R = + constructRationalFunction( + this * other.numerator, + other.denominator + ) + + /** + * Returns sum of the polynomial represented as rational function and the rational function. + */ + public override operator fun R.plus(other: P): R = + constructRationalFunction( + numerator + denominator * other, + denominator + ) + /** + * Returns difference between the polynomial represented as rational function and the rational function. + */ + public override operator fun R.minus(other: P): R = + constructRationalFunction( + numerator - denominator * other, + denominator + ) + /** + * Returns product of the polynomial represented as rational function and the rational function. + */ + public override operator fun R.times(other: P): R = + constructRationalFunction( + numerator * other, + denominator + ) + + /** + * 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 + ) + + /** + * Instance of zero rational function (zero of the rational functions ring). + */ + public override val zero: R get() = constructRationalFunction(polynomialZero, polynomialOne) + + /** + * Instance of unit polynomial (unit of the rational functions ring). + */ + public override val one: R get() = constructRationalFunction(polynomialOne, polynomialOne) } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt index 9b5022f85..09b0b25ae 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt @@ -64,205 +64,25 @@ public class LabeledRationalFunction( public class LabeledRationalFunctionSpace>( public val ring: A, -) : AbstractRationalFunctionalSpaceOverPolynomialSpace< - C, - LabeledPolynomial, - LabeledRationalFunction, - LabeledPolynomialSpace, - > { +) : + AbstractRationalFunctionalSpaceOverPolynomialSpace< + C, + LabeledPolynomial, + LabeledRationalFunction, + LabeledPolynomialSpace, + >, + AbstractPolynomialFractionsSpace< + C, + LabeledPolynomial, + LabeledRationalFunction, + >() { override val polynomialRing : LabeledPolynomialSpace = LabeledPolynomialSpace(ring) - - /** - * Returns sum of the rational function and the integer represented as rational function. - * - * The operation is equivalent to adding [other] copies of unit polynomial to [this]. - */ - public override operator fun LabeledRationalFunction.plus(other: Int): LabeledRationalFunction = - LabeledRationalFunction( - numerator + denominator * other, - denominator - ) - /** - * Returns difference between the rational function and the integer represented as rational function. - * - * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. - */ - public override operator fun LabeledRationalFunction.minus(other: Int): LabeledRationalFunction = - LabeledRationalFunction( - numerator - denominator * other, - denominator - ) - /** - * Returns product of the rational function and the integer represented as rational function. - * - * The operation is equivalent to sum of [other] copies of [this]. - */ - public override operator fun LabeledRationalFunction.times(other: Int): LabeledRationalFunction = - LabeledRationalFunction( - numerator * other, - denominator - ) - - /** - * Returns sum of the integer represented as 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: LabeledRationalFunction): LabeledRationalFunction = - LabeledRationalFunction( - other.denominator * this + other.numerator, - other.denominator - ) - /** - * Returns difference between the integer represented as 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: LabeledRationalFunction): LabeledRationalFunction = - LabeledRationalFunction( - other.denominator * this - other.numerator, - other.denominator - ) - /** - * Returns product of the integer represented as rational function and the rational function. - * - * The operation is equivalent to sum of [this] copies of [other]. - */ - public override operator fun Int.times(other: LabeledRationalFunction): LabeledRationalFunction = - LabeledRationalFunction( - this * other.numerator, - other.denominator - ) - - /** - * Returns sum of the constant represented as rational function and the rational function. - */ - public override operator fun C.plus(other: LabeledRationalFunction): LabeledRationalFunction = - LabeledRationalFunction( - other.denominator * this + other.numerator, - other.denominator - ) - /** - * Returns difference between the constant represented as polynomial and the rational function. - */ - public override operator fun C.minus(other: LabeledRationalFunction): LabeledRationalFunction = - LabeledRationalFunction( - other.denominator * this - other.numerator, - other.denominator - ) - /** - * Returns product of the constant represented as polynomial and the rational function. - */ - public override operator fun C.times(other: LabeledRationalFunction): LabeledRationalFunction = - LabeledRationalFunction( - this * other.numerator, - other.denominator - ) - - /** - * Returns sum of the constant represented as rational function and the rational function. - */ - public override operator fun LabeledRationalFunction.plus(other: C): LabeledRationalFunction = - LabeledRationalFunction( - numerator + denominator * other, - denominator - ) - /** - * Returns difference between the constant represented as rational function and the rational function. - */ - public override operator fun LabeledRationalFunction.minus(other: C): LabeledRationalFunction = - LabeledRationalFunction( - numerator - denominator * other, - denominator - ) - /** - * Returns product of the constant represented as rational function and the rational function. - */ - public override operator fun LabeledRationalFunction.times(other: C): LabeledRationalFunction = - LabeledRationalFunction( - numerator * other, - denominator - ) - - /** - * Returns sum of the polynomial represented as rational function and the rational function. - */ - public override operator fun LabeledPolynomial.plus(other: LabeledRationalFunction): LabeledRationalFunction = - LabeledRationalFunction( - other.denominator * this + other.numerator, - other.denominator - ) - /** - * Returns difference between the polynomial represented as polynomial and the rational function. - */ - public override operator fun LabeledPolynomial.minus(other: LabeledRationalFunction): LabeledRationalFunction = - LabeledRationalFunction( - other.denominator * this - other.numerator, - other.denominator - ) - /** - * Returns product of the polynomial represented as polynomial and the rational function. - */ - public override operator fun LabeledPolynomial.times(other: LabeledRationalFunction): LabeledRationalFunction = - LabeledRationalFunction( - this * other.numerator, - other.denominator - ) - - /** - * Returns sum of the polynomial represented as rational function and the rational function. - */ - public override operator fun LabeledRationalFunction.plus(other: LabeledPolynomial): LabeledRationalFunction = - LabeledRationalFunction( - numerator + denominator * other, - denominator - ) - /** - * Returns difference between the polynomial represented as rational function and the rational function. - */ - public override operator fun LabeledRationalFunction.minus(other: LabeledPolynomial): LabeledRationalFunction = - LabeledRationalFunction( - numerator - denominator * other, - denominator - ) - /** - * Returns product of the polynomial represented as rational function and the rational function. - */ - public override operator fun LabeledRationalFunction.times(other: LabeledPolynomial): LabeledRationalFunction = - LabeledRationalFunction( - numerator * other, - denominator - ) - - /** - * Returns negation of the rational function. - */ - public override operator fun LabeledRationalFunction.unaryMinus(): LabeledRationalFunction = LabeledRationalFunction(-numerator, denominator) - /** - * Returns sum of the rational functions. - */ - public override operator fun LabeledRationalFunction.plus(other: LabeledRationalFunction): LabeledRationalFunction = - LabeledRationalFunction( - numerator * other.denominator + denominator * other.numerator, - denominator * other.denominator - ) - /** - * Returns difference of the rational functions. - */ - public override operator fun LabeledRationalFunction.minus(other: LabeledRationalFunction): LabeledRationalFunction = - LabeledRationalFunction( - numerator * other.denominator - denominator * other.numerator, - denominator * other.denominator - ) - /** - * Returns product of the rational functions. - */ - public override operator fun LabeledRationalFunction.times(other: LabeledRationalFunction): LabeledRationalFunction = - LabeledRationalFunction( - numerator * other.numerator, - denominator * other.denominator - ) + override fun constructRationalFunction( + numerator: LabeledPolynomial, + denominator: LabeledPolynomial + ): LabeledRationalFunction = + LabeledRationalFunction(numerator, denominator) /** * Instance of zero rational function (zero of the rational functions ring). @@ -279,7 +99,7 @@ public class LabeledRationalFunctionSpace>( public override infix fun LabeledRationalFunction.equalsTo(other: LabeledRationalFunction): Boolean { if (this === other) return true - if ( !(numerator.isZero() xor other.numerator.isZero()) ) return false + if (numerator.isZero() != other.numerator.isZero()) return false val variables = this.variables union other.variables val thisNumeratorDegrees = this.numerator.degrees diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt index 78ba233f5..4927460fb 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt @@ -60,205 +60,25 @@ public class NumberedRationalFunction internal constructor( public class NumberedRationalFunctionSpace> ( public val ring: A, -) : AbstractRationalFunctionalSpaceOverPolynomialSpace< - C, - NumberedPolynomial, - NumberedRationalFunction, - NumberedPolynomialSpace, - > { +) : + AbstractRationalFunctionalSpaceOverPolynomialSpace< + C, + NumberedPolynomial, + NumberedRationalFunction, + NumberedPolynomialSpace, + >, + AbstractPolynomialFractionsSpace< + C, + NumberedPolynomial, + NumberedRationalFunction, + >() { override val polynomialRing : NumberedPolynomialSpace = NumberedPolynomialSpace(ring) - - /** - * Returns sum of the rational function and the integer represented as rational function. - * - * The operation is equivalent to adding [other] copies of unit polynomial to [this]. - */ - public override operator fun NumberedRationalFunction.plus(other: Int): NumberedRationalFunction = - NumberedRationalFunction( - numerator + denominator * other, - denominator - ) - /** - * Returns difference between the rational function and the integer represented as rational function. - * - * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. - */ - public override operator fun NumberedRationalFunction.minus(other: Int): NumberedRationalFunction = - NumberedRationalFunction( - numerator - denominator * other, - denominator - ) - /** - * Returns product of the rational function and the integer represented as rational function. - * - * The operation is equivalent to sum of [other] copies of [this]. - */ - public override operator fun NumberedRationalFunction.times(other: Int): NumberedRationalFunction = - NumberedRationalFunction( - numerator * other, - denominator - ) - - /** - * Returns sum of the integer represented as 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: NumberedRationalFunction): NumberedRationalFunction = - NumberedRationalFunction( - other.denominator * this + other.numerator, - other.denominator - ) - /** - * Returns difference between the integer represented as 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: NumberedRationalFunction): NumberedRationalFunction = - NumberedRationalFunction( - other.denominator * this - other.numerator, - other.denominator - ) - /** - * Returns product of the integer represented as rational function and the rational function. - * - * The operation is equivalent to sum of [this] copies of [other]. - */ - public override operator fun Int.times(other: NumberedRationalFunction): NumberedRationalFunction = - NumberedRationalFunction( - this * other.numerator, - other.denominator - ) - - /** - * Returns sum of the constant represented as rational function and the rational function. - */ - public override operator fun C.plus(other: NumberedRationalFunction): NumberedRationalFunction = - NumberedRationalFunction( - other.denominator * this + other.numerator, - other.denominator - ) - /** - * Returns difference between the constant represented as polynomial and the rational function. - */ - public override operator fun C.minus(other: NumberedRationalFunction): NumberedRationalFunction = - NumberedRationalFunction( - other.denominator * this - other.numerator, - other.denominator - ) - /** - * Returns product of the constant represented as polynomial and the rational function. - */ - public override operator fun C.times(other: NumberedRationalFunction): NumberedRationalFunction = - NumberedRationalFunction( - this * other.numerator, - other.denominator - ) - - /** - * Returns sum of the constant represented as rational function and the rational function. - */ - public override operator fun NumberedRationalFunction.plus(other: C): NumberedRationalFunction = - NumberedRationalFunction( - numerator + denominator * other, - denominator - ) - /** - * Returns difference between the constant represented as rational function and the rational function. - */ - public override operator fun NumberedRationalFunction.minus(other: C): NumberedRationalFunction = - NumberedRationalFunction( - numerator - denominator * other, - denominator - ) - /** - * Returns product of the constant represented as rational function and the rational function. - */ - public override operator fun NumberedRationalFunction.times(other: C): NumberedRationalFunction = - NumberedRationalFunction( - numerator * other, - denominator - ) - - /** - * Returns sum of the polynomial represented as rational function and the rational function. - */ - public override operator fun NumberedPolynomial.plus(other: NumberedRationalFunction): NumberedRationalFunction = - NumberedRationalFunction( - other.denominator * this + other.numerator, - other.denominator - ) - /** - * Returns difference between the polynomial represented as polynomial and the rational function. - */ - public override operator fun NumberedPolynomial.minus(other: NumberedRationalFunction): NumberedRationalFunction = - NumberedRationalFunction( - other.denominator * this - other.numerator, - other.denominator - ) - /** - * Returns product of the polynomial represented as polynomial and the rational function. - */ - public override operator fun NumberedPolynomial.times(other: NumberedRationalFunction): NumberedRationalFunction = - NumberedRationalFunction( - this * other.numerator, - other.denominator - ) - - /** - * Returns sum of the polynomial represented as rational function and the rational function. - */ - public override operator fun NumberedRationalFunction.plus(other: NumberedPolynomial): NumberedRationalFunction = - NumberedRationalFunction( - numerator + denominator * other, - denominator - ) - /** - * Returns difference between the polynomial represented as rational function and the rational function. - */ - public override operator fun NumberedRationalFunction.minus(other: NumberedPolynomial): NumberedRationalFunction = - NumberedRationalFunction( - numerator - denominator * other, - denominator - ) - /** - * Returns product of the polynomial represented as rational function and the rational function. - */ - public override operator fun NumberedRationalFunction.times(other: NumberedPolynomial): NumberedRationalFunction = - NumberedRationalFunction( - numerator * other, - denominator - ) - - /** - * Returns negation of the rational function. - */ - public override operator fun NumberedRationalFunction.unaryMinus(): NumberedRationalFunction = NumberedRationalFunction(-numerator, denominator) - /** - * Returns sum of the rational functions. - */ - public override operator fun NumberedRationalFunction.plus(other: NumberedRationalFunction): NumberedRationalFunction = - NumberedRationalFunction( - numerator * other.denominator + denominator * other.numerator, - denominator * other.denominator - ) - /** - * Returns difference of the rational functions. - */ - public override operator fun NumberedRationalFunction.minus(other: NumberedRationalFunction): NumberedRationalFunction = - NumberedRationalFunction( - numerator * other.denominator - denominator * other.numerator, - denominator * other.denominator - ) - /** - * Returns product of the rational functions. - */ - public override operator fun NumberedRationalFunction.times(other: NumberedRationalFunction): NumberedRationalFunction = - NumberedRationalFunction( - numerator * other.numerator, - denominator * other.denominator - ) + override fun constructRationalFunction( + numerator: NumberedPolynomial, + denominator: NumberedPolynomial + ): NumberedRationalFunction = + NumberedRationalFunction(numerator, denominator) /** * Instance of zero rational function (zero of the rational functions ring). @@ -275,7 +95,7 @@ public class NumberedRationalFunctionSpace> ( public override infix fun NumberedRationalFunction.equalsTo(other: NumberedRationalFunction): Boolean { if (this === other) return true - if ( !(numerator.isZero() xor other.numerator.isZero()) ) return false + if (numerator.isZero() != other.numerator.isZero()) return false val countOfVariables = max(this.lastVariable, other.lastVariable) val thisNumeratorDegrees = this.numerator.degrees diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index 226eddce9..506aa4004 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -42,205 +42,22 @@ public data class RationalFunction internal constructor ( public class RationalFunctionSpace> ( public val ring: A, -) : AbstractRationalFunctionalSpaceOverPolynomialSpace< - C, - Polynomial, - RationalFunction, - PolynomialSpace, - > { +) : + AbstractRationalFunctionalSpaceOverPolynomialSpace< + C, + Polynomial, + RationalFunction, + PolynomialSpace, + >, + AbstractPolynomialFractionsSpace< + C, + Polynomial, + RationalFunction, + >() { override val polynomialRing : PolynomialSpace = PolynomialSpace(ring) - - /** - * Returns sum of the rational function and the integer represented as rational function. - * - * The operation is equivalent to adding [other] copies of unit polynomial to [this]. - */ - public override operator fun RationalFunction.plus(other: Int): RationalFunction = - RationalFunction( - numerator + denominator * other, - denominator - ) - /** - * Returns difference between the rational function and the integer represented as rational function. - * - * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. - */ - public override operator fun RationalFunction.minus(other: Int): RationalFunction = - RationalFunction( - numerator - denominator * other, - denominator - ) - /** - * Returns product of the rational function and the integer represented as rational function. - * - * The operation is equivalent to sum of [other] copies of [this]. - */ - public override operator fun RationalFunction.times(other: Int): RationalFunction = - RationalFunction( - numerator * other, - denominator - ) - - /** - * Returns sum of the integer represented as 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: RationalFunction): RationalFunction = - RationalFunction( - other.denominator * this + other.numerator, - other.denominator - ) - /** - * Returns difference between the integer represented as 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: RationalFunction): RationalFunction = - RationalFunction( - other.denominator * this - other.numerator, - other.denominator - ) - /** - * Returns product of the integer represented as rational function and the rational function. - * - * The operation is equivalent to sum of [this] copies of [other]. - */ - public override operator fun Int.times(other: RationalFunction): RationalFunction = - RationalFunction( - this * other.numerator, - other.denominator - ) - - /** - * Returns sum of the constant represented as rational function and the rational function. - */ - public override operator fun C.plus(other: RationalFunction): RationalFunction = - RationalFunction( - other.denominator * this + other.numerator, - other.denominator - ) - /** - * Returns difference between the constant represented as polynomial and the rational function. - */ - public override operator fun C.minus(other: RationalFunction): RationalFunction = - RationalFunction( - other.denominator * this - other.numerator, - other.denominator - ) - /** - * Returns product of the constant represented as polynomial and the rational function. - */ - public override operator fun C.times(other: RationalFunction): RationalFunction = - RationalFunction( - this * other.numerator, - other.denominator - ) - - /** - * Returns sum of the constant represented as rational function and the rational function. - */ - public override operator fun RationalFunction.plus(other: C): RationalFunction = - RationalFunction( - numerator + denominator * other, - denominator - ) - /** - * Returns difference between the constant represented as rational function and the rational function. - */ - public override operator fun RationalFunction.minus(other: C): RationalFunction = - RationalFunction( - numerator - denominator * other, - denominator - ) - /** - * Returns product of the constant represented as rational function and the rational function. - */ - public override operator fun RationalFunction.times(other: C): RationalFunction = - RationalFunction( - numerator * other, - denominator - ) - - /** - * Returns sum of the polynomial represented as rational function and the rational function. - */ - public override operator fun Polynomial.plus(other: RationalFunction): RationalFunction = - RationalFunction( - other.denominator * this + other.numerator, - other.denominator - ) - /** - * Returns difference between the polynomial represented as polynomial and the rational function. - */ - public override operator fun Polynomial.minus(other: RationalFunction): RationalFunction = - RationalFunction( - other.denominator * this - other.numerator, - other.denominator - ) - /** - * Returns product of the polynomial represented as polynomial and the rational function. - */ - public override operator fun Polynomial.times(other: RationalFunction): RationalFunction = - RationalFunction( - this * other.numerator, - other.denominator - ) - - /** - * Returns sum of the polynomial represented as rational function and the rational function. - */ - public override operator fun RationalFunction.plus(other: Polynomial): RationalFunction = - RationalFunction( - numerator + denominator * other, - denominator - ) - /** - * Returns difference between the polynomial represented as rational function and the rational function. - */ - public override operator fun RationalFunction.minus(other: Polynomial): RationalFunction = - RationalFunction( - numerator - denominator * other, - denominator - ) - /** - * Returns product of the polynomial represented as rational function and the rational function. - */ - public override operator fun RationalFunction.times(other: Polynomial): RationalFunction = - RationalFunction( - numerator * other, - denominator - ) - - /** - * Returns negation of the rational function. - */ - public override operator fun RationalFunction.unaryMinus(): RationalFunction = RationalFunction(-numerator, denominator) - /** - * Returns sum of the rational functions. - */ - public override operator fun RationalFunction.plus(other: RationalFunction): RationalFunction = - RationalFunction( - numerator * other.denominator + denominator * other.numerator, - denominator * other.denominator - ) - /** - * Returns difference of the rational functions. - */ - public override operator fun RationalFunction.minus(other: RationalFunction): RationalFunction = - RationalFunction( - numerator * other.denominator - denominator * other.numerator, - denominator * other.denominator - ) - /** - * Returns product of the rational functions. - */ - public override operator fun RationalFunction.times(other: RationalFunction): RationalFunction = - RationalFunction( - numerator * other.numerator, - denominator * other.denominator - ) + override fun constructRationalFunction(numerator: Polynomial, denominator: Polynomial): RationalFunction = + RationalFunction(numerator, denominator) /** * Instance of zero rational function (zero of the rational functions ring). @@ -251,16 +68,6 @@ public class RationalFunctionSpace> ( */ public override val one: RationalFunction = RationalFunction(polynomialOne, polynomialOne) - /** - * Checks equality of the rational functions. - */ - public override infix fun RationalFunction.equalsTo(other: RationalFunction): Boolean = - when { - this === other -> true - numeratorDegree - denominatorDegree != with(other) { numeratorDegree - denominatorDegree } -> false - else -> numerator * other.denominator equalsTo other.numerator * denominator - } - // TODO: Разобрать public operator fun RationalFunction.div(other: RationalFunction): RationalFunction = -- 2.34.1 From 51b0d232b561ecc57fe6d6660c9a9d104a447dd2 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Mon, 21 Mar 2022 23:21:55 +0300 Subject: [PATCH 052/275] Renamed `AbstractPolynomialFractionsSpace` to `PolynomialSpaceOfFractions` --- .../kscience/kmath/functions/AbstractRationalFunction.kt | 5 ++--- .../kscience/kmath/functions/LabeledRationalFunction.kt | 2 +- .../kscience/kmath/functions/NumberedRationalFunction.kt | 2 +- .../space/kscience/kmath/functions/RationalFunction.kt | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt index 7feab3dfb..c9c0b3920 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt @@ -867,8 +867,7 @@ public interface AbstractRationalFunctionalSpaceOverPolynomialSpace< /** * 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. + * [C]. It also assumes that there is provided constructor * * @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. @@ -876,7 +875,7 @@ public interface AbstractRationalFunctionalSpaceOverPolynomialSpace< * @param AP the type of algebraic structure (precisely, of ring) provided for polynomials. */ // TODO: Add support of field @Suppress("INAPPLICABLE_JVM_NAME") -public abstract class AbstractPolynomialFractionsSpace< +public abstract class PolynomialSpaceOfFractions< C, P: AbstractPolynomial, R: AbstractRationalFunction, diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt index 09b0b25ae..92bd344ac 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt @@ -71,7 +71,7 @@ public class LabeledRationalFunctionSpace>( LabeledRationalFunction, LabeledPolynomialSpace, >, - AbstractPolynomialFractionsSpace< + PolynomialSpaceOfFractions< C, LabeledPolynomial, LabeledRationalFunction, diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt index 4927460fb..4da715e3f 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt @@ -67,7 +67,7 @@ public class NumberedRationalFunctionSpace> ( NumberedRationalFunction, NumberedPolynomialSpace, >, - AbstractPolynomialFractionsSpace< + PolynomialSpaceOfFractions< C, NumberedPolynomial, NumberedRationalFunction, diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index 506aa4004..51c1e2f80 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -49,7 +49,7 @@ public class RationalFunctionSpace> ( RationalFunction, PolynomialSpace, >, - AbstractPolynomialFractionsSpace< + PolynomialSpaceOfFractions< C, Polynomial, RationalFunction, -- 2.34.1 From c6d1068df465dca4374dde7cb1395cb9dbcff8f9 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Mon, 21 Mar 2022 23:47:10 +0300 Subject: [PATCH 053/275] Renamed `Polynomial`, etc. to `ListPolynomial`, etc. and `AbstractPolynomial` to `Polynomial`. As it was advised by @CommanderTvis. --- .../kmath/functions/AbstractPolynomial.kt | 389 ------ .../functions/AbstractRationalFunction.kt | 1085 --------------- .../kmath/functions/LabeledPolynomial.kt | 4 +- .../functions/LabeledRationalFunction.kt | 4 +- .../kmath/functions/ListPolynomial.kt | 491 +++++++ .../kmath/functions/ListRationalFunction.kt | 154 +++ .../kmath/functions/NumberedPolynomial.kt | 4 +- .../functions/NumberedRationalFunction.kt | 4 +- .../kscience/kmath/functions/Piecewise.kt | 22 +- .../kscience/kmath/functions/Polynomial.kt | 644 ++++----- .../kmath/functions/RationalFunction.kt | 1175 +++++++++++++++-- .../functions/labeledRationalFunctionUtil.kt | 2 +- ...olynomialUtil.kt => listPolynomialUtil.kt} | 66 +- ...ionUtil.kt => listRationalFunctionUtil.kt} | 26 +- .../functions/numberedRationalFunctionUtil.kt | 2 +- .../kmath/interpolation/LinearInterpolator.kt | 4 +- .../kmath/interpolation/SplineInterpolator.kt | 4 +- .../kmath/functions/ListPolynomialTest.kt | 705 ++++++++++ .../kmath/functions/ListPolynomialUtilTest.kt | 229 ++++ .../kmath/functions/PolynomialTest.kt | 691 ---------- .../kmath/functions/PolynomialUtilTest.kt | 229 ---- .../kmath/integration/SplineIntegralTest.kt | 4 +- .../kscience/kmath/test/misc/IntModulo.kt | 14 +- 23 files changed, 2983 insertions(+), 2969 deletions(-) delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt rename kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/{polynomialUtil.kt => listPolynomialUtil.kt} (72%) rename kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/{rationalFunctionUtil.kt => listRationalFunctionUtil.kt} (88%) create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt deleted file mode 100644 index fd1b51fae..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractPolynomial.kt +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.operations.* -import kotlin.js.JsName -import kotlin.jvm.JvmName - - -/** - * Abstraction of polynomials. - */ -public interface AbstractPolynomial - -/** - * 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") -public interface AbstractPolynomialSpace> : Ring

{ - /** - * Returns sum of the constant and the integer represented as constant (member of underlying ring). - * - * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. - */ - public operator fun C.plus(other: Int): C - /** - * Returns difference between the constant and the integer represented as constant (member of underlying ring). - * - * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. - */ - public operator fun C.minus(other: Int): C - /** - * Returns product of the constant and the integer represented as constant (member of underlying ring). - * - * The operation is equivalent to sum of [other] copies of [this]. - */ - public operator fun C.times(other: Int): C - - /** - * Returns sum of the integer represented as constant (member of underlying ring) and the constant. - * - * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. - */ - public operator fun Int.plus(other: C): C - /** - * Returns difference between the integer represented as constant (member of underlying ring) and the constant. - * - * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. - */ - public operator fun Int.minus(other: C): C - /** - * Returns product of the integer represented as constant (member of underlying ring) and the constant. - * - * The operation is equivalent to sum of [this] copies of [other]. - */ - public operator fun Int.times(other: C): C - - /** - * Returns sum of the polynomial and the integer represented as polynomial. - * - * The operation is equivalent to adding [other] copies of unit polynomial to [this]. - */ - public operator fun P.plus(other: Int): P = addMultipliedBySquaring(this, one, other) - /** - * Returns difference between the polynomial and the integer represented as polynomial. - * - * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. - */ - public operator fun P.minus(other: Int): P = addMultipliedBySquaring(this, one, -other) - /** - * Returns product of the polynomial and the integer represented as polynomial. - * - * The operation is equivalent to sum of [other] copies of [this]. - */ - public operator fun P.times(other: Int): P = multiplyBySquaring(this, other) - - /** - * Returns sum of the integer represented as 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 = addMultipliedBySquaring(other, one, this) - /** - * Returns difference between the integer represented as 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 = addMultipliedBySquaring(-other, one, this) - /** - * Returns product of the integer represented as polynomial and the polynomial. - * - * The operation is equivalent to sum of [this] copies of [other]. - */ - public operator fun Int.times(other: P): P = multiplyBySquaring(other, this) - - /** - * Returns the same constant. - */ - @JvmName("constantUnaryPlus") - @JsName("constantUnaryPlus") - public operator fun C.unaryPlus(): C = this - /** - * Returns negation of the constant. - */ - @JvmName("constantUnaryMinus") - @JsName("constantUnaryMinus") - public operator fun C.unaryMinus(): C - /** - * Returns sum of the constants. - */ - @JvmName("constantPlus") - @JsName("constantPlus") - public operator fun C.plus(other: C): C - /** - * Returns difference of the constants. - */ - @JvmName("constantMinus") - @JsName("constantMinus") - public operator fun C.minus(other: C): C - /** - * Returns product of the constants. - */ - @JvmName("constantTimes") - @JsName("constantTimes") - public operator fun C.times(other: C): C - /** - * Raises [arg] to the integer power [exponent]. - */ - @JvmName("constantPower") - @JsName("constantPower") - public fun power(arg: C, exponent: UInt) : C - - /** - * Check if the instant is zero constant. - */ - public fun C.isZero(): Boolean = this == constantZero - /** - * Check if the instant is NOT zero constant. - */ - public fun C.isNotZero(): Boolean = !isZero() - /** - * Check if the instant is unit constant. - */ - public fun C.isOne(): Boolean = this == constantOne - /** - * Check if the instant is NOT unit constant. - */ - public fun C.isNotOne(): Boolean = !isOne() - /** - * Check if the instant is minus unit constant. - */ - public fun C.isMinusOne(): Boolean = this == -constantOne - /** - * Check if the instant is NOT minus unit constant. - */ - public fun C.isNotMinusOne(): Boolean = !isMinusOne() - - /** - * 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 polynomial and the polynomial. - */ - public operator fun C.plus(other: P): P - /** - * Returns difference between the constant represented as polynomial and the polynomial. - */ - public operator fun C.minus(other: P): P - /** - * Returns product of the constant represented as polynomial and the polynomial. - */ - public operator fun C.times(other: P): P - - /** - * Returns sum of the constant represented as polynomial and the polynomial. - */ - public operator fun P.plus(other: C): P - /** - * Returns difference between the constant represented as polynomial and the polynomial. - */ - public operator fun P.minus(other: C): P - /** - * Returns product of the constant represented as polynomial and the polynomial. - */ - public operator fun P.times(other: C): P - - /** - * 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 = exponentiationBySquaring(arg, exponent) - - /** - * Check if the instant is zero polynomial. - */ - public fun P.isZero(): Boolean = this equalsTo zero - /** - * Check if the instant is NOT zero polynomial. - */ - public fun P.isNotZero(): Boolean = !isZero() - /** - * Check if the instant is unit polynomial. - */ - public fun P.isOne(): Boolean = this equalsTo one - /** - * Check if the instant is NOT unit polynomial. - */ - public fun P.isNotOne(): Boolean = !isOne() - /** - * Check if the instant is minus unit polynomial. - */ - public fun P.isMinusOne(): Boolean = this equalsTo -one - /** - * Check if the instant is NOT minus unit polynomial. - */ - public fun P.isNotMinusOne(): Boolean = !isMinusOne() - - /** - * 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 - - /** - * Checks equality of the polynomials. - */ - public infix fun P.equalsTo(other: P): Boolean - /** - * Checks NOT equality of the polynomials. - */ - public infix fun P.notEqualsTo(other: P): Boolean = !(this equalsTo other) - - /** - * 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 - - /** - * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. - */ - public fun P.isConstant(): Boolean = degree <= 0 - /** - * Checks if the instant is **not** constant polynomial (of degree no more than 0) over considered ring. - */ - public fun P.isNotConstant(): Boolean = !isConstant() - /** - * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. - */ - public fun P.isNonZeroConstant(): Boolean = degree == 0 - /** - * Checks if the instant is **not** constant non-zero polynomial (of degree no more than 0) over considered ring. - */ - public fun P.isNotNonZeroConstant(): Boolean = !isNonZeroConstant() - /** - * If polynomial is a constant polynomial represents and returns it as constant. - * Otherwise, (when the polynomial is not constant polynomial) returns `null`. - */ - public fun P.asConstantOrNull(): C? - /** - * If polynomial is a constant polynomial represents and returns it as constant. - * Otherwise, (when the polynomial is not constant polynomial) raises corresponding exception. - */ - public fun P.asConstant(): C = requireNotNull(asConstantOrNull()) { "Can not represent non-constant polynomial as a constant" } - - 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") -public interface AbstractPolynomialSpaceOverRing, A: Ring> : AbstractPolynomialSpace { - - public val ring: A - - /** - * Returns sum of the constant and the integer represented as constant (member of underlying ring). - * - * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. - */ - public override operator fun C.plus(other: Int): C = ring { addMultipliedBySquaring(this@plus, one, other) } - /** - * Returns difference between the constant and the integer represented as constant (member of underlying ring). - * - * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. - */ - public override operator fun C.minus(other: Int): C = ring { addMultipliedBySquaring(this@minus, one, -other) } - /** - * Returns product of the constant and the integer represented as constant (member of underlying ring). - * - * The operation is equivalent to sum of [other] copies of [this]. - */ - public override operator fun C.times(other: Int): C = ring { multiplyBySquaring(this@times, other) } - - /** - * Returns sum of the integer represented as constant (member of underlying ring) and the constant. - * - * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. - */ - public override operator fun Int.plus(other: C): C = ring { addMultipliedBySquaring(other, one, this@plus) } - /** - * Returns difference between the integer represented as constant (member of underlying ring) and the constant. - * - * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. - */ - public override operator fun Int.minus(other: C): C = ring { addMultipliedBySquaring(-other, one, this@minus) } - /** - * Returns product of the integer represented as constant (member of underlying ring) and the constant. - * - * The operation is equivalent to sum of [this] copies of [other]. - */ - public override operator fun Int.times(other: C): C = ring { multiplyBySquaring(other, this@times) } - - /** - * Returns negation of the constant. - */ - @JvmName("constantUnaryMinus") - public override operator fun C.unaryMinus(): C = ring { -this@unaryMinus } - /** - * Returns sum of the constants. - */ - @JvmName("constantPlus") - public override operator fun C.plus(other: C): C = ring { this@plus + other } - /** - * Returns difference of the constants. - */ - @JvmName("constantMinus") - public override operator fun C.minus(other: C): C = ring { this@minus - other } - /** - * Returns product of the constants. - */ - @JvmName("constantTimes") - public override operator fun C.times(other: C): C = ring { this@times * other } - /** - * Raises [arg] to the integer power [exponent]. - */ - @JvmName("constantPower") - 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 -} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt deleted file mode 100644 index c9c0b3920..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/AbstractRationalFunction.kt +++ /dev/null @@ -1,1085 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.operations.* -import kotlin.js.JsName -import kotlin.jvm.JvmName - - -/** - * Abstraction of rational function. - */ -public interface AbstractRationalFunction> { - 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 in them. - * @param R the type of rational functions. - */ // TODO: Add support of field -@Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") -public interface AbstractRationalFunctionalSpace, R: AbstractRationalFunction> : Ring { - /** - * Returns sum of the constant and the integer represented as constant (member of underlying ring). - * - * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. - */ - public operator fun C.plus(other: Int): C - /** - * Returns difference between the constant and the integer represented as constant (member of underlying ring). - * - * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. - */ - public operator fun C.minus(other: Int): C - /** - * Returns product of the constant and the integer represented as constant (member of underlying ring). - * - * The operation is equivalent to sum of [other] copies of [this]. - */ - public operator fun C.times(other: Int): C - - /** - * Returns sum of the integer represented as constant (member of underlying ring) and the constant. - * - * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. - */ - public operator fun Int.plus(other: C): C - /** - * Returns difference between the integer represented as constant (member of underlying ring) and the constant. - * - * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. - */ - public operator fun Int.minus(other: C): C - /** - * Returns product of the integer represented as constant (member of underlying ring) and the constant. - * - * The operation is equivalent to sum of [this] copies of [other]. - */ - public operator fun Int.times(other: C): C - - /** - * Returns sum of the constant and the integer represented as polynomial. - * - * The operation is equivalent to adding [other] copies of unit polynomial to [this]. - */ - public operator fun P.plus(other: Int): P - /** - * Returns difference between the constant and the integer represented as polynomial. - * - * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. - */ - public operator fun P.minus(other: Int): P - /** - * Returns product of the constant and the integer represented as polynomial. - * - * The operation is equivalent to sum of [other] copies of [this]. - */ - public operator fun P.times(other: Int): P - - /** - * Returns sum of the integer represented as polynomial and the constant. - * - * The operation is equivalent to adding [this] copies of unit polynomial to [other]. - */ - public operator fun Int.plus(other: P): P - /** - * Returns difference between the integer represented as polynomial and the constant. - * - * The operation is equivalent to subtraction [this] copies of unit polynomial from [other]. - */ - public operator fun Int.minus(other: P): P - /** - * Returns product of the integer represented as polynomial and the constant. - * - * The operation is equivalent to sum of [this] copies of [other]. - */ - public operator fun Int.times(other: P): P - - /** - * Returns sum of the rational function and the integer represented as rational function. - * - * The operation is equivalent to adding [other] copies of unit polynomial to [this]. - */ - public operator fun R.plus(other: Int): R = addMultipliedBySquaring(this, one, other) - /** - * Returns difference between the rational function and the integer represented as rational function. - * - * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. - */ - public operator fun R.minus(other: Int): R = addMultipliedBySquaring(this, one, -other) - /** - * Returns product of the rational function and the integer represented as rational function. - * - * The operation is equivalent to sum of [other] copies of [this]. - */ - public operator fun R.times(other: Int): R = multiplyBySquaring(this, other) - - /** - * Returns sum of the integer represented as 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 = addMultipliedBySquaring(other, one, this) - /** - * Returns difference between the integer represented as 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 = addMultipliedBySquaring(-other, one, this) - /** - * Returns product of the integer represented as 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 = multiplyBySquaring(other, this) - - /** - * Returns the same constant. - */ - @JvmName("constantUnaryPlus") - @JsName("constantUnaryPlus") - public operator fun C.unaryPlus(): C = this - /** - * Returns negation of the constant. - */ - @JvmName("constantUnaryMinus") - @JsName("constantUnaryMinus") - public operator fun C.unaryMinus(): C - /** - * Returns sum of the constants. - */ - @JvmName("constantPlus") - @JsName("constantPlus") - public operator fun C.plus(other: C): C - /** - * Returns difference of the constants. - */ - @JvmName("constantMinus") - @JsName("constantMinus") - public operator fun C.minus(other: C): C - /** - * Returns product of the constants. - */ - @JvmName("constantTimes") - @JsName("constantTimes") - public operator fun C.times(other: C): C - /** - * Raises [arg] to the integer power [exponent]. - */ - @JvmName("constantPower") - @JsName("constantPower") - public fun power(arg: C, exponent: UInt) : C - - /** - * Check if the instant is zero constant. - */ - public fun C.isZero(): Boolean = this == constantZero - /** - * Check if the instant is NOT zero constant. - */ - public fun C.isNotZero(): Boolean = !isZero() - /** - * Check if the instant is unit constant. - */ - public fun C.isOne(): Boolean = this == constantOne - /** - * Check if the instant is NOT unit constant. - */ - public fun C.isNotOne(): Boolean = !isOne() - /** - * Check if the instant is minus unit constant. - */ - public fun C.isMinusOne(): Boolean = this == -constantOne - /** - * Check if the instant is NOT minus unit constant. - */ - public fun C.isNotMinusOne(): Boolean = !isMinusOne() - - /** - * 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 polynomial and the polynomial. - */ - public operator fun C.plus(other: P): P - /** - * Returns difference between the constant represented as polynomial and the polynomial. - */ - public operator fun C.minus(other: P): P - /** - * Returns product of the constant represented as polynomial and the polynomial. - */ - public operator fun C.times(other: P): P - - /** - * Returns sum of the constant represented as polynomial and the polynomial. - */ - public operator fun P.plus(other: C): P - /** - * Returns difference between the constant represented as polynomial and the polynomial. - */ - public operator fun P.minus(other: C): P - /** - * Returns product of the constant represented as polynomial and the polynomial. - */ - public operator fun P.times(other: C): P - - /** - * Returns the same polynomial. - */ - public operator fun P.unaryPlus(): P = this - /** - * Returns negation of the polynomial. - */ - public operator fun P.unaryMinus(): P - /** - * Returns sum of the polynomials. - */ - public operator fun P.plus(other: P): P - /** - * Returns difference of the polynomials. - */ - public operator fun P.minus(other: P): P - /** - * Returns product of the polynomials. - */ - public operator fun P.times(other: P): P - /** - * Raises [arg] to the integer power [exponent]. - */ - public fun power(arg: P, exponent: UInt) : P - - /** - * Check if the instant is zero polynomial. - */ - public fun P.isZero(): Boolean = this equalsTo polynomialZero - /** - * Check if the instant is NOT zero polynomial. - */ - public fun P.isNotZero(): Boolean = !isZero() - /** - * Check if the instant is unit polynomial. - */ - public fun P.isOne(): Boolean = this equalsTo polynomialOne - /** - * Check if the instant is NOT unit polynomial. - */ - public fun P.isNotOne(): Boolean = !isOne() - /** - * Check if the instant is minus unit polynomial. - */ - public fun P.isMinusOne(): Boolean = this equalsTo -polynomialOne - /** - * Check if the instant is NOT minus unit polynomial. - */ - public fun P.isNotMinusOne(): Boolean = !isMinusOne() - - /** - * 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 - - /** - * Checks equality of the polynomials. - */ - public infix fun P.equalsTo(other: P): Boolean - /** - * Checks NOT equality of the polynomials. - */ - public infix fun P.notEqualsTo(other: P): Boolean = !(this equalsTo other) - - /** - * Returns sum of the constant represented as rational function and the rational function. - */ - public operator fun C.plus(other: R): R - /** - * Returns difference between the constant represented as polynomial and the rational function. - */ - public operator fun C.minus(other: R): R - /** - * Returns product of the constant represented as polynomial and the rational function. - */ - public operator fun C.times(other: R): R - - /** - * Returns sum of the constant represented as rational function and the rational function. - */ - public operator fun R.plus(other: C): R - /** - * Returns difference between the constant represented as rational function and the rational function. - */ - public operator fun R.minus(other: C): R - /** - * Returns product of the constant represented as rational function and the rational function. - */ - public operator fun R.times(other: C): R - - /** - * Returns sum of the polynomial represented as rational function and the rational function. - */ - public operator fun P.plus(other: R): R - /** - * Returns difference between the polynomial represented as polynomial and the rational function. - */ - public operator fun P.minus(other: R): R - /** - * Returns product of the polynomial represented as polynomial and the rational function. - */ - public operator fun P.times(other: R): R - - /** - * Returns sum of the polynomial represented as rational function and the rational function. - */ - public operator fun R.plus(other: P): R - /** - * Returns difference between the polynomial represented as rational function and the rational function. - */ - public operator fun R.minus(other: P): R - /** - * Returns product of the polynomial represented as rational function and the rational function. - */ - public operator fun R.times(other: P): R - - /** - * 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 - /** - * Raises [arg] to the integer power [exponent]. - */ - public override fun power(arg: R, exponent: UInt) : R = exponentiationBySquaring(arg, exponent) - - /** - * Check if the instant is zero rational function. - */ - public fun R.isZero(): Boolean = numerator equalsTo polynomialZero - /** - * Check if the instant is NOT zero rational function. - */ - public fun R.isNotZero(): Boolean = !isZero() - /** - * Check if the instant is unit rational function. - */ - public fun R.isOne(): Boolean = numerator equalsTo denominator - /** - * Check if the instant is NOT unit rational function. - */ - public fun R.isNotOne(): Boolean = !isOne() - /** - * Check if the instant is minus unit rational function. - */ - public fun R.isMinusOne(): Boolean = (numerator + denominator).isZero() - /** - * Check if the instant is NOT minus unit rational function. - */ - public fun R.isNotMinusOne(): Boolean = !isMinusOne() - - /** - * 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 - - /** - * Checks equality of the rational functions. - */ - public infix fun R.equalsTo(other: R): Boolean = - when { - this === other -> true - numerator.isZero() != other.numerator.isZero() -> false - numeratorDegree - denominatorDegree != with(other) { numeratorDegree - denominatorDegree } -> false - else -> numerator * other.denominator equalsTo other.numerator * denominator - } - /** - * Checks NOT equality of the polynomials. - */ - public infix fun R.notEqualsTo(other: R): Boolean = !(this equalsTo other) - - /** - * 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 - - /** - * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. - */ - public fun P.isConstant(): Boolean = degree <= 0 - /** - * Checks if the instant is **not** constant polynomial (of degree no more than 0) over considered ring. - */ - public fun P.isNotConstant(): Boolean = !isConstant() - /** - * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. - */ - public fun P.isNonZeroConstant(): Boolean = degree == 0 - /** - * Checks if the instant is **not** constant non-zero polynomial (of degree no more than 0) over considered ring. - */ - public fun P.isNotNonZeroConstant(): Boolean = !isNonZeroConstant() - /** - * If polynomial is a constant polynomial represents and returns it as constant. - * Otherwise, (when the polynomial is not constant polynomial) returns `null`. - */ - public fun P.asConstantOrNull(): C? - /** - * If polynomial is a constant polynomial represents and returns it as constant. - * Otherwise, (when the polynomial is not constant polynomial) raises corresponding exception. - */ - public fun P.asConstant(): C = requireNotNull(asConstantOrNull()) { "Can not represent non-constant polynomial as a constant" } - - /** - * 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. - */ // TODO: Add support of field -@Suppress("INAPPLICABLE_JVM_NAME") -public interface AbstractRationalFunctionalSpaceOverRing, R: AbstractRationalFunction, A: Ring> : AbstractRationalFunctionalSpace { - - public val ring: A - - /** - * Returns sum of the constant and the integer represented as constant (member of underlying ring). - * - * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. - */ - public override operator fun C.plus(other: Int): C = ring { addMultipliedBySquaring(this@plus, one, other) } - /** - * Returns difference between the constant and the integer represented as constant (member of underlying ring). - * - * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. - */ - public override operator fun C.minus(other: Int): C = ring { addMultipliedBySquaring(this@minus, one, -other) } - /** - * Returns product of the constant and the integer represented as constant (member of underlying ring). - * - * The operation is equivalent to sum of [other] copies of [this]. - */ - public override operator fun C.times(other: Int): C = ring { multiplyBySquaring(this@times, other) } - - /** - * Returns sum of the integer represented as constant (member of underlying ring) and the constant. - * - * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. - */ - public override operator fun Int.plus(other: C): C = ring { addMultipliedBySquaring(other, one, this@plus) } - /** - * Returns difference between the integer represented as constant (member of underlying ring) and the constant. - * - * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. - */ - public override operator fun Int.minus(other: C): C = ring { addMultipliedBySquaring(-other, one, this@minus) } - /** - * Returns product of the integer represented as constant (member of underlying ring) and the constant. - * - * The operation is equivalent to sum of [this] copies of [other]. - */ - public override operator fun Int.times(other: C): C = ring { multiplyBySquaring(other, this@times) } - - /** - * Returns the same constant. - */ - @JvmName("constantUnaryPlus") - public override operator fun C.unaryPlus(): C = ring { +this@unaryPlus } - /** - * Returns negation of the constant. - */ - @JvmName("constantUnaryMinus") - public override operator fun C.unaryMinus(): C = ring { -this@unaryMinus } - /** - * Returns sum of the constants. - */ - @JvmName("constantPlus") - public override operator fun C.plus(other: C): C = ring { this@plus + other } - /** - * Returns difference of the constants. - */ - @JvmName("constantMinus") - public override operator fun C.minus(other: C): C = ring { this@minus - other } - /** - * Returns product of the constants. - */ - @JvmName("constantTimes") - public override operator fun C.times(other: C): C = ring { this@times * other } - /** - * Raises [arg] to the integer power [exponent]. - */ - @JvmName("constantPower") - 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. - */ // TODO: Add support of field -@Suppress("INAPPLICABLE_JVM_NAME") -public interface AbstractRationalFunctionalSpaceOverPolynomialSpace< - C, - P: AbstractPolynomial, - R: AbstractRationalFunction, - AP: AbstractPolynomialSpace, - > : AbstractRationalFunctionalSpace { - - public val polynomialRing: AP - - /** - * Returns sum of the constant and the integer represented as constant (member of underlying ring). - * - * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. - */ - public override operator fun C.plus(other: Int): C = polynomialRing { this@plus + other } - /** - * Returns difference between the constant and the integer represented as constant (member of underlying ring). - * - * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. - */ - public override operator fun C.minus(other: Int): C = polynomialRing { this@minus - other } - /** - * Returns product of the constant and the integer represented as constant (member of underlying ring). - * - * The operation is equivalent to sum of [other] copies of [this]. - */ - public override operator fun C.times(other: Int): C = polynomialRing { this@times * other } - - /** - * Returns sum of the integer represented as constant (member of underlying ring) and the constant. - * - * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. - */ - public override operator fun Int.plus(other: C): C = polynomialRing { this@plus + other } - /** - * Returns difference between the integer represented as constant (member of underlying ring) and the constant. - * - * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. - */ - public override operator fun Int.minus(other: C): C = polynomialRing { this@minus - other } - /** - * Returns product of the integer represented as constant (member of underlying ring) and the constant. - * - * The operation is equivalent to sum of [this] copies of [other]. - */ - public override operator fun Int.times(other: C): C = polynomialRing { this@times * other } - - /** - * Returns sum of the constant and the integer represented as polynomial. - * - * The operation is equivalent to adding [other] copies of unit polynomial to [this]. - */ - public override operator fun P.plus(other: Int): P = polynomialRing { this@plus + other } - /** - * Returns difference between the constant and the integer represented as polynomial. - * - * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. - */ - public override operator fun P.minus(other: Int): P = polynomialRing { this@minus - other } - /** - * Returns product of the constant and the integer represented as polynomial. - * - * The operation is equivalent to sum of [other] copies of [this]. - */ - public override operator fun P.times(other: Int): P = polynomialRing { this@times * other } - - /** - * Returns sum of the integer represented as polynomial and the constant. - * - * The operation is equivalent to adding [this] copies of unit polynomial to [other]. - */ - public override operator fun Int.plus(other: P): P = polynomialRing { this@plus + other } - /** - * Returns difference between the integer represented as polynomial and the constant. - * - * The operation is equivalent to subtraction [this] copies of unit polynomial from [other]. - */ - public override operator fun Int.minus(other: P): P = polynomialRing { this@minus - other } - /** - * Returns product of the integer represented as polynomial and the constant. - * - * The operation is equivalent to sum of [this] copies of [other]. - */ - public override operator fun Int.times(other: P): P = polynomialRing { this@times * other } - - /** - * Returns the same constant. - */ - @JvmName("constantUnaryPlus") - public override operator fun C.unaryPlus(): C = polynomialRing { +this@unaryPlus } - /** - * Returns negation of the constant. - */ - @JvmName("constantUnaryMinus") - public override operator fun C.unaryMinus(): C = polynomialRing { -this@unaryMinus } - /** - * Returns sum of the constants. - */ - @JvmName("constantPlus") - public override operator fun C.plus(other: C): C = polynomialRing { this@plus + other } - /** - * Returns difference of the constants. - */ - @JvmName("constantMinus") - public override operator fun C.minus(other: C): C = polynomialRing { this@minus - other } - /** - * Returns product of the constants. - */ - @JvmName("constantTimes") - public override operator fun C.times(other: C): C = polynomialRing { this@times * other } - /** - * Raises [arg] to the integer power [exponent]. - */ - @JvmName("constantPower") - public override fun power(arg: C, exponent: UInt) : C = polynomialRing { power(arg, exponent) } - - /** - * Check if the instant is zero constant. - */ - public override fun C.isZero(): Boolean = polynomialRing { this@isZero.isZero() } - /** - * Check if the instant is NOT zero constant. - */ - public override fun C.isNotZero(): Boolean = polynomialRing { this@isNotZero.isNotZero() } - /** - * Check if the instant is unit constant. - */ - public override fun C.isOne(): Boolean = polynomialRing { this@isOne.isOne() } - /** - * Check if the instant is NOT unit constant. - */ - public override fun C.isNotOne(): Boolean = polynomialRing { this@isNotOne.isNotOne() } - /** - * Check if the instant is minus unit constant. - */ - public override fun C.isMinusOne(): Boolean = polynomialRing { this@isMinusOne.isMinusOne() } - /** - * Check if the instant is NOT minus unit constant. - */ - public override fun C.isNotMinusOne(): Boolean = polynomialRing { this@isNotMinusOne.isNotMinusOne() } - - /** - * 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 polynomial and the polynomial. - */ - public override operator fun C.plus(other: P): P = polynomialRing { this@plus + other } - /** - * Returns difference between the constant represented as polynomial and the polynomial. - */ - public override operator fun C.minus(other: P): P = polynomialRing { this@minus - other } - /** - * Returns product of the constant represented as polynomial and the polynomial. - */ - public override operator fun C.times(other: P): P = polynomialRing { this@times * other } - - /** - * Returns sum of the constant represented as polynomial and the polynomial. - */ - public override operator fun P.plus(other: C): P = polynomialRing { this@plus + other } - /** - * Returns difference between the constant represented as polynomial and the polynomial. - */ - public override operator fun P.minus(other: C): P = polynomialRing { this@minus - other } - /** - * Returns product of the constant represented as polynomial and the polynomial. - */ - public override operator fun P.times(other: C): P = polynomialRing { this@times * other } - - /** - * Returns the same polynomial. - */ - public override operator fun P.unaryPlus(): P = polynomialRing { +this@unaryPlus } - /** - * Returns negation of the polynomial. - */ - public override operator fun P.unaryMinus(): P = polynomialRing { -this@unaryMinus } - /** - * Returns sum of the polynomials. - */ - public override operator fun P.plus(other: P): P = polynomialRing { this@plus + other } - /** - * Returns difference of the polynomials. - */ - public override operator fun P.minus(other: P): P = polynomialRing { this@minus - other } - /** - * Returns product of the polynomials. - */ - public override operator fun P.times(other: P): P = polynomialRing { this@times * other } - /** - * Raises [arg] to the integer power [exponent]. - */ - public override fun power(arg: P, exponent: UInt) : P = polynomialRing { power(arg, exponent) } - - /** - * Check if the instant is zero polynomial. - */ - public override fun P.isZero(): Boolean = polynomialRing { this@isZero.isZero() } - /** - * Check if the instant is NOT zero polynomial. - */ - public override fun P.isNotZero(): Boolean = polynomialRing { this@isNotZero.isNotZero() } - /** - * Check if the instant is unit polynomial. - */ - public override fun P.isOne(): Boolean = polynomialRing { this@isOne.isOne() } - /** - * Check if the instant is NOT unit polynomial. - */ - public override fun P.isNotOne(): Boolean = polynomialRing { this@isNotOne.isNotOne() } - /** - * Check if the instant is minus unit polynomial. - */ - public override fun P.isMinusOne(): Boolean = polynomialRing { this@isMinusOne.isMinusOne() } - /** - * Check if the instant is NOT minus unit polynomial. - */ - public override fun P.isNotMinusOne(): Boolean = polynomialRing { this@isNotMinusOne.isNotMinusOne() } - - /** - * 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 - - /** - * Checks equality of the polynomials. - */ - public override infix fun P.equalsTo(other: P): Boolean = polynomialRing { this@equalsTo equalsTo other } - /** - * Checks NOT equality of the polynomials. - */ - public override infix fun P.notEqualsTo(other: P): Boolean = polynomialRing { this@notEqualsTo notEqualsTo other } - - /** - * 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 } - - /** - * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. - */ - public override fun P.isConstant(): Boolean = polynomialRing { this@isConstant.isConstant() } - /** - * Checks if the instant is **not** constant polynomial (of degree no more than 0) over considered ring. - */ - public override fun P.isNotConstant(): Boolean = polynomialRing { this@isNotConstant.isNotConstant() } - /** - * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. - */ - public override fun P.isNonZeroConstant(): Boolean = polynomialRing { this@isNonZeroConstant.isNonZeroConstant() } - /** - * Checks if the instant is **not** constant non-zero polynomial (of degree no more than 0) over considered ring. - */ - public override fun P.isNotNonZeroConstant(): Boolean = polynomialRing { this@isNotNonZeroConstant.isNotNonZeroConstant() } - /** - * If polynomial is a constant polynomial represents and returns it as constant. - * Otherwise, (when the polynomial is not constant polynomial) returns `null`. - */ - public override fun P.asConstantOrNull(): C? = polynomialRing { this@asConstantOrNull.asConstantOrNull() } - /** - * If polynomial is a constant polynomial represents and returns it as constant. - * Otherwise, (when the polynomial is not constant polynomial) raises corresponding exception. - */ - public override fun P.asConstant(): C = polynomialRing { this@asConstant.asConstant() } -} - -/** - * 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 - * - * @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. - */ // TODO: Add support of field -@Suppress("INAPPLICABLE_JVM_NAME") -public abstract class PolynomialSpaceOfFractions< - C, - P: AbstractPolynomial, - R: AbstractRationalFunction, - > : AbstractRationalFunctionalSpace { - protected abstract fun constructRationalFunction(numerator: P, denominator: P) : R - - /** - * Returns sum of the rational function and the integer represented as 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 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 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 sum of the integer represented as 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 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 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 sum of the constant represented as rational function and the rational function. - */ - public override operator fun C.plus(other: R): R = - constructRationalFunction( - other.denominator * this + other.numerator, - other.denominator - ) - /** - * Returns difference between the constant represented as polynomial and the rational function. - */ - public override operator fun C.minus(other: R): R = - constructRationalFunction( - other.denominator * this - other.numerator, - other.denominator - ) - /** - * Returns product of the constant represented as polynomial and the rational function. - */ - public override operator fun C.times(other: R): R = - constructRationalFunction( - this * other.numerator, - other.denominator - ) - - /** - * Returns sum of the constant represented as rational function and the rational function. - */ - public override operator fun R.plus(other: C): R = - constructRationalFunction( - numerator + denominator * other, - denominator - ) - /** - * Returns difference between the constant represented as rational function and the rational function. - */ - public override operator fun R.minus(other: C): R = - constructRationalFunction( - numerator - denominator * other, - denominator - ) - /** - * Returns product of the constant represented as rational function and the rational function. - */ - public override operator fun R.times(other: C): R = - constructRationalFunction( - numerator * other, - denominator - ) - - /** - * Returns sum of the polynomial represented as rational function and the rational function. - */ - public override operator fun P.plus(other: R): R = - constructRationalFunction( - other.denominator * this + other.numerator, - other.denominator - ) - /** - * Returns difference between the polynomial represented as polynomial and the rational function. - */ - public override operator fun P.minus(other: R): R = - constructRationalFunction( - other.denominator * this - other.numerator, - other.denominator - ) - /** - * Returns product of the polynomial represented as polynomial and the rational function. - */ - public override operator fun P.times(other: R): R = - constructRationalFunction( - this * other.numerator, - other.denominator - ) - - /** - * Returns sum of the polynomial represented as rational function and the rational function. - */ - public override operator fun R.plus(other: P): R = - constructRationalFunction( - numerator + denominator * other, - denominator - ) - /** - * Returns difference between the polynomial represented as rational function and the rational function. - */ - public override operator fun R.minus(other: P): R = - constructRationalFunction( - numerator - denominator * other, - denominator - ) - /** - * Returns product of the polynomial represented as rational function and the rational function. - */ - public override operator fun R.times(other: P): R = - constructRationalFunction( - numerator * other, - denominator - ) - - /** - * 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 - ) - - /** - * Instance of zero rational function (zero of the rational functions ring). - */ - public override val zero: R get() = constructRationalFunction(polynomialZero, polynomialOne) - - /** - * Instance of unit polynomial (unit of the rational functions ring). - */ - public override val one: R get() = constructRationalFunction(polynomialOne, polynomialOne) -} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt index 76f5fc29c..968f77b20 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -44,7 +44,7 @@ internal constructor( * where `a`, `b` and `c` are corresponding [Symbol] objects. */ public val coefficients: Map, C> -) : AbstractPolynomial { +) : Polynomial { override fun toString(): String = "LabeledPolynomial$coefficients" } @@ -116,7 +116,7 @@ public fun C.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomia */ public class LabeledPolynomialSpace>( public override val ring: A, -) : AbstractPolynomialSpaceOverRing, A> { +) : PolynomialSpaceOverRing, A> { public operator fun Symbol.plus(other: Int): LabeledPolynomial = if (other == 0) LabeledPolynomial(mapOf( mapOf(this@plus to 1U) to constantOne, diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt index 92bd344ac..f347f9191 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt @@ -13,7 +13,7 @@ import space.kscience.kmath.operations.invoke public class LabeledRationalFunction( public override val numerator: LabeledPolynomial, public override val denominator: LabeledPolynomial -) : AbstractRationalFunction> { +) : RationalFunction> { override fun toString(): String = "LabeledRationalFunction${numerator.coefficients}/${denominator.coefficients}" } @@ -65,7 +65,7 @@ public class LabeledRationalFunction( public class LabeledRationalFunctionSpace>( public val ring: A, ) : - AbstractRationalFunctionalSpaceOverPolynomialSpace< + RationalFunctionalSpaceOverPolynomialSpace< C, LabeledPolynomial, LabeledRationalFunction, diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt new file mode 100644 index 000000000..b97c1e0b4 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt @@ -0,0 +1,491 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.* +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract +import kotlin.experimental.ExperimentalTypeInference +import kotlin.jvm.JvmName +import kotlin.math.max +import kotlin.math.min + +/** + * Polynomial model without fixation on specific context they are applied to. + * + * @param coefficients constant is the leftmost coefficient. + */ +public data class ListPolynomial( + /** + * List that collects coefficients of the polynomial. Every monomial `a x^d` is represented as a coefficients + * `a` placed into the list with index `d`. For example coefficients of 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 recommended not to put extra zeros at end of the list (as for `0x^3` and `0x^4` in the example), but is not + * prohibited. + */ + public val coefficients: List +) : Polynomial { + override fun toString(): String = "Polynomial$coefficients" +} + +/** + * Returns a [ListPolynomial] instance with given [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 }) + +/** + * Returns a [ListPolynomial] instance with given [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() }) + +public fun C.asPolynomial() : ListPolynomial = ListPolynomial(listOf(this)) + +/** + * Space of univariate 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 open class ListPolynomialSpace>( + public override val ring: A, +) : PolynomialSpaceOverRing, A> { + /** + * Returns sum of the polynomial and the integer represented as 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 + val isResultZero = result.isZero() + + when { + size == 0 && !isResultZero -> add(result) + size > 1 || !isResultZero -> this[0] = result + else -> clear() + } + } + ) + /** + * Returns difference between the polynomial and the integer represented as 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 + val isResultZero = result.isZero() + + when { + size == 0 && !isResultZero -> add(result) + size > 1 || !isResultZero -> this[0] = result + else -> clear() + } + } + ) + /** + * Returns product of the polynomial and the integer represented as polynomial. + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + public override operator fun ListPolynomial.times(other: Int): ListPolynomial = + if (other == 0) zero + else ListPolynomial( + coefficients + .applyAndRemoveZeros { + for (deg in indices) this[deg] = this[deg] * other + } + ) + + /** + * Returns sum of the integer represented as 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 } + val isResultZero = result.isZero() + + when { + size == 0 && !isResultZero -> add(result) + size > 1 || !isResultZero -> this[0] = result + else -> clear() + } + } + ) + /** + * Returns difference between the integer represented as 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 = + if (this == 0) other + else + ListPolynomial( + other.coefficients + .toMutableList() + .apply { + forEachIndexed { index, c -> if (index != 0) this[index] = -c } + + val result = this@minus - getOrElse(0) { constantZero } + val isResultZero = result.isZero() + + when { + size == 0 && !isResultZero -> add(result) + size > 1 || !isResultZero -> this[0] = result + else -> clear() + } + } + ) + /** + * Returns product of the integer represented as polynomial and the polynomial. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + public override operator fun Int.times(other: ListPolynomial): ListPolynomial = + if (this == 0) zero + else ListPolynomial( + other.coefficients + .applyAndRemoveZeros { + for (deg in indices) this[deg] = this@times * this[deg] + } + ) + + /** + * Returns sum of the constant represented as polynomial and the polynomial. + */ + public override operator fun C.plus(other: ListPolynomial): ListPolynomial = + if (this.isZero()) other + else 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) + val isResultZero = result.isZero() + + when { + size == 0 && !isResultZero -> add(result) + size > 1 || !isResultZero -> this[0] = result + else -> clear() + } + } + ) + } + /** + * Returns difference between the constant represented as polynomial and the polynomial. + */ + public override operator fun C.minus(other: ListPolynomial): ListPolynomial = + if (this.isZero()) other + else with(other.coefficients) { + if (isEmpty()) ListPolynomial(listOf(this@minus)) + else ListPolynomial( + toMutableList() + .apply { + forEachIndexed { index, c -> if (index != 0) this[index] = -c } + + val result = if (size == 0) this@minus else this@minus - get(0) + val isResultZero = result.isZero() + + when { + size == 0 && !isResultZero -> add(result) + size > 1 || !isResultZero -> this[0] = result + else -> clear() + } + } + ) + } + /** + * Returns product of the constant represented as polynomial and the polynomial. + */ + public override operator fun C.times(other: ListPolynomial): ListPolynomial = + if (this.isZero()) other + else ListPolynomial( + other.coefficients + .applyAndRemoveZeros { + for (deg in indices) this[deg] = this@times * this[deg] + } + ) + + /** + * Returns sum of the constant represented as polynomial and the polynomial. + */ + public override operator fun ListPolynomial.plus(other: C): ListPolynomial = + if (other.isZero()) this + else with(coefficients) { + if (isEmpty()) ListPolynomial(listOf(other)) + else ListPolynomial( + toMutableList() + .apply { + val result = if (size == 0) other else get(0) + other + val isResultZero = result.isZero() + + when { + size == 0 && !isResultZero -> add(result) + size > 1 || !isResultZero -> this[0] = result + else -> clear() + } + } + ) + } + /** + * Returns difference between the constant represented as polynomial and the polynomial. + */ + public override operator fun ListPolynomial.minus(other: C): ListPolynomial = + if (other.isZero()) this + else with(coefficients) { + if (isEmpty()) ListPolynomial(listOf(-other)) + else ListPolynomial( + toMutableList() + .apply { + val result = if (size == 0) other else get(0) - other + val isResultZero = result.isZero() + + when { + size == 0 && !isResultZero -> add(result) + size > 1 || !isResultZero -> this[0] = result + else -> clear() + } + } + ) + } + /** + * Returns product of the constant represented as polynomial and the polynomial. + */ + public override operator fun ListPolynomial.times(other: C): ListPolynomial = + if (other.isZero()) this + else ListPolynomial( + coefficients + .applyAndRemoveZeros { + for (deg in indices) this[deg] = this[deg] * other + } + ) + + /** + * 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( + Coefficients(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( + Coefficients(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 when { + thisDegree == -1 -> zero + otherDegree == -1 -> zero + else -> + ListPolynomial( + Coefficients(thisDegree + otherDegree + 1) { d -> + (max(0, d - otherDegree)..min(thisDegree, d)) + .map { coefficients[it] * other.coefficients[d - it] } + .reduce { acc, rational -> acc + rational } + } + ) + } + } + + /** + * Check if the instant is zero polynomial. + */ + public override fun ListPolynomial.isZero(): Boolean = coefficients.all { it.isZero() } + /** + * Check if the instant is unit polynomial. + */ + public override fun ListPolynomial.isOne(): Boolean = + with(coefficients) { + isNotEmpty() && withIndex().all { (index, c) -> if (index == 0) c.isOne() else c.isZero() } + } + /** + * Check if the instant is minus unit polynomial. + */ + public override fun ListPolynomial.isMinusOne(): Boolean = + with(coefficients) { + isNotEmpty() && withIndex().all { (index, c) -> if (index == 0) c.isMinusOne() else c.isZero() } + } + + /** + * Instance of zero polynomial (zero of the polynomial ring). + */ + override val zero: ListPolynomial = ListPolynomial(emptyList()) + /** + * Instance of unit constant (unit of the underlying ring). + */ + override val one: ListPolynomial = ListPolynomial(listOf(constantOne)) + + /** + * Checks equality of the polynomials. + */ + public override infix fun ListPolynomial.equalsTo(other: ListPolynomial): Boolean = + when { + this === other -> true + this.degree == other.degree -> (0..degree).all { coefficients[it] == other.coefficients[it] } + else -> false + } + + /** + * 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.indexOfLast { it != constantZero } + + /** + * If polynomial is a constant polynomial represents and returns it as constant. + * Otherwise, (when the polynomial is not constant polynomial) returns `null`. + */ + public override fun ListPolynomial.asConstantOrNull(): C? = + with(coefficients) { + when { + isEmpty() -> constantZero + withIndex().all { (index, c) -> index == 0 || c.isZero() } -> first() + else -> null + } + } + + @Suppress("NOTHING_TO_INLINE") + public inline fun ListPolynomial.substitute(argument: C): C = this.substitute(ring, argument) + @Suppress("NOTHING_TO_INLINE") + public inline fun ListPolynomial.substitute(argument: ListPolynomial): ListPolynomial = this.substitute(ring, argument) + + @Suppress("NOTHING_TO_INLINE") + public inline fun ListPolynomial.asFunction(): (C) -> C = { this.substitute(ring, it) } + @Suppress("NOTHING_TO_INLINE") + public inline fun ListPolynomial.asFunctionOnConstants(): (C) -> C = { this.substitute(ring, it) } + @Suppress("NOTHING_TO_INLINE") + public inline fun ListPolynomial.asFunctionOnPolynomials(): (ListPolynomial) -> ListPolynomial = { this.substitute(ring, it) } + + /** + * Evaluates the polynomial for the given value [argument]. + */ + @Suppress("NOTHING_TO_INLINE") + public inline operator fun ListPolynomial.invoke(argument: C): C = this.substitute(ring, argument) + @Suppress("NOTHING_TO_INLINE") + public inline operator fun ListPolynomial.invoke(argument: ListPolynomial): ListPolynomial = this.substitute(ring, argument) + + // TODO: Move to other internal utilities with context receiver + @JvmName("applyAndRemoveZerosInternal") + internal inline fun MutableList.applyAndRemoveZeros(block: MutableList.() -> Unit) : MutableList { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + block() + while (isNotEmpty() && elementAt(lastIndex).isZero()) removeAt(lastIndex) + return this + } + internal inline fun List.applyAndRemoveZeros(block: MutableList.() -> Unit) : List = + toMutableList().applyAndRemoveZeros(block) + @Suppress("FunctionName") + internal inline fun MutableCoefficients(size: Int, init: (index: Int) -> C): MutableList { + val list = ArrayList(size) + repeat(size) { index -> list.add(init(index)) } + with(list) { while (isNotEmpty() && elementAt(lastIndex).isZero()) removeAt(lastIndex) } + return list + } + @Suppress("FunctionName") + internal inline fun Coefficients(size: Int, init: (index: Int) -> C): List = MutableCoefficients(size, init) + @OptIn(ExperimentalTypeInference::class) + internal inline fun buildCoefficients(@BuilderInference builderAction: MutableList.() -> Unit): List { + contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } + return buildList { + builderAction() + while (isNotEmpty() && elementAt(lastIndex).isZero()) removeAt(lastIndex) + } + } + @OptIn(ExperimentalTypeInference::class) + internal inline fun buildCoefficients(capacity: Int, @BuilderInference builderAction: MutableList.() -> Unit): List { + contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } + return buildList(capacity) { + builderAction() + while (isNotEmpty() && elementAt(lastIndex).isZero()) removeAt(lastIndex) + } + } +} + +/** + * 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-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt new file mode 100644 index 000000000..50ddd3118 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt @@ -0,0 +1,154 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.Ring + + +public data class ListRationalFunction internal constructor ( + public override val numerator: ListPolynomial, + public override val denominator: ListPolynomial +) : RationalFunction> { + override fun toString(): String = "RationalFunction${numerator.coefficients}/${denominator.coefficients}" +} + +// Waiting for context receivers :( TODO: Replace with context receivers when they will be available + +//context(RationalFunctionSpace) +//@Suppress("FunctionName") +//internal fun > RationalFunction(numerator: Polynomial, denominator: Polynomial): RationalFunction = +// if (denominator.isZero()) throw ArithmeticException("/ by zero") +// else RationalFunction(numerator, denominator) +//context(RationalFunctionSpace) +//@Suppress("FunctionName") +//public fun > RationalFunction(numeratorCoefficients: List, denominatorCoefficients: List, reverse: Boolean = false): RationalFunction = +// RationalFunction( +// Polynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), +// Polynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } ).also { if (it.isZero()) } +// ) +//context(RationalFunctionSpace) +//@Suppress("FunctionName") +//public fun > RationalFunction(numerator: Polynomial): RationalFunction = +// RationalFunction(numerator, onePolynomial) +//context(RationalFunctionSpace) +//@Suppress("FunctionName") +//public fun > RationalFunction(numeratorCoefficients: List, reverse: Boolean = false): RationalFunction = +// RationalFunction( +// Polynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ) +// ) + +public class ListRationalFunctionSpace> ( + public val ring: A, +) : + RationalFunctionalSpaceOverPolynomialSpace< + C, + ListPolynomial, + ListRationalFunction, + ListPolynomialSpace, + >, + PolynomialSpaceOfFractions< + C, + ListPolynomial, + ListRationalFunction, + >() { + + override val polynomialRing : ListPolynomialSpace = ListPolynomialSpace(ring) + override fun constructRationalFunction(numerator: ListPolynomial, denominator: ListPolynomial): ListRationalFunction = + ListRationalFunction(numerator, denominator) + + /** + * Instance of zero rational function (zero of the rational functions ring). + */ + public override val zero: ListRationalFunction = ListRationalFunction(polynomialZero, polynomialOne) + /** + * Instance of unit polynomial (unit of the rational functions ring). + */ + public override val one: ListRationalFunction = ListRationalFunction(polynomialOne, polynomialOne) + + // TODO: Разобрать + + public operator fun ListRationalFunction.div(other: ListRationalFunction): ListRationalFunction = + ListRationalFunction( + numerator * other.denominator, + denominator * other.numerator + ) + + public operator fun ListRationalFunction.div(other: ListPolynomial): ListRationalFunction = + ListRationalFunction( + numerator, + denominator * other + ) + + public operator fun ListRationalFunction.div(other: C): ListRationalFunction = + ListRationalFunction( + numerator, + denominator * other + ) + + public operator fun ListRationalFunction.div(other: Int): ListRationalFunction = + ListRationalFunction( + numerator, + denominator * other + ) + +// operator fun invoke(arg: UnivariatePolynomial): RationalFunction = +// RationalFunction( +// numerator(arg), +// denominator(arg) +// ) +// +// operator fun invoke(arg: RationalFunction): RationalFunction { +// val num = numerator invokeRFTakeNumerator arg +// val den = denominator invokeRFTakeNumerator arg +// val degreeDif = numeratorDegree - denominatorDegree +// return if (degreeDif > 0) +// RationalFunction( +// num, +// multiplyByPower(den, arg.denominator, degreeDif) +// ) +// else +// RationalFunction( +// multiplyByPower(num, arg.denominator, -degreeDif), +// den +// ) +// } +// +// override fun toString(): String = toString(UnivariatePolynomial.variableName) +// +// fun toString(withVariableName: String = UnivariatePolynomial.variableName): String = +// when(true) { +// numerator.isZero() -> "0" +// denominator.isOne() -> numerator.toString(withVariableName) +// else -> "${numerator.toStringWithBrackets(withVariableName)}/${denominator.toStringWithBrackets(withVariableName)}" +// } +// +// fun toStringWithBrackets(withVariableName: String = UnivariatePolynomial.variableName): String = +// when(true) { +// numerator.isZero() -> "0" +// denominator.isOne() -> numerator.toStringWithBrackets(withVariableName) +// else -> "(${numerator.toStringWithBrackets(withVariableName)}/${denominator.toStringWithBrackets(withVariableName)})" +// } +// +// fun toReversedString(withVariableName: String = UnivariatePolynomial.variableName): String = +// when(true) { +// numerator.isZero() -> "0" +// denominator.isOne() -> numerator.toReversedString(withVariableName) +// else -> "${numerator.toReversedStringWithBrackets(withVariableName)}/${denominator.toReversedStringWithBrackets(withVariableName)}" +// } +// +// fun toReversedStringWithBrackets(withVariableName: String = UnivariatePolynomial.variableName): String = +// when(true) { +// numerator.isZero() -> "0" +// denominator.isOne() -> numerator.toReversedStringWithBrackets(withVariableName) +// else -> "(${numerator.toReversedStringWithBrackets(withVariableName)}/${denominator.toReversedStringWithBrackets(withVariableName)})" +// } +// +// fun removeZeros() = +// RationalFunction( +// numerator.removeZeros(), +// denominator.removeZeros() +// ) +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index c05bc30ec..3b9b907b7 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -43,7 +43,7 @@ internal constructor( * contain any zeros on end, but can contain zeros on start or anywhere in middle. */ public val coefficients: Map, C> -) : AbstractPolynomial { +) : Polynomial { override fun toString(): String = "NumberedPolynomial$coefficients" } @@ -112,7 +112,7 @@ public fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolyno */ public open class NumberedPolynomialSpace>( public final override val ring: A, -) : AbstractPolynomialSpaceOverRing, A> { +) : PolynomialSpaceOverRing, A> { /** * Returns sum of the polynomial and the integer represented as polynomial. * diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt index 4da715e3f..f3b90b5c5 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt @@ -12,7 +12,7 @@ import kotlin.math.max public class NumberedRationalFunction internal constructor( public override val numerator: NumberedPolynomial, public override val denominator: NumberedPolynomial -) : AbstractRationalFunction> { +) : RationalFunction> { override fun toString(): String = "NumberedRationalFunction${numerator.coefficients}/${denominator.coefficients}" } @@ -61,7 +61,7 @@ public class NumberedRationalFunction internal constructor( public class NumberedRationalFunctionSpace> ( public val ring: A, ) : - AbstractRationalFunctionalSpaceOverPolynomialSpace< + RationalFunctionalSpaceOverPolynomialSpace< C, NumberedPolynomial, NumberedRationalFunction, diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt index cfd21d552..612b00535 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt @@ -27,10 +27,10 @@ public fun interface Piecewise { * @property pieces An ordered list of range-polynomial pairs. The list does not in general guarantee that there are no * "holes" in it. */ -public interface PiecewisePolynomial> : Piecewise> { - public val pieces: Collection, Polynomial>> +public interface PiecewisePolynomial> : Piecewise> { + public val pieces: Collection, ListPolynomial>> - override fun findPiece(arg: T): Polynomial? + override fun findPiece(arg: T): ListPolynomial? } /** @@ -38,11 +38,11 @@ public interface PiecewisePolynomial> : Piecewise> PiecewisePolynomial( - pieces: Collection, Polynomial>>, + pieces: Collection, ListPolynomial>>, ): PiecewisePolynomial = object : PiecewisePolynomial { - override val pieces: Collection, Polynomial>> = pieces + override val pieces: Collection, ListPolynomial>> = pieces - override fun findPiece(arg: T): Polynomial? = pieces.firstOrNull { arg in it.first }?.second + override fun findPiece(arg: T): ListPolynomial? = pieces.firstOrNull { arg in it.first }?.second } /** @@ -50,10 +50,10 @@ public fun > PiecewisePolynomial( * The pieces search is logarithmic. */ private class OrderedPiecewisePolynomial>( - override val pieces: List, Polynomial>>, + override val pieces: List, ListPolynomial>>, ) : PiecewisePolynomial { - override fun findPiece(arg: T): Polynomial? { + override fun findPiece(arg: T): ListPolynomial? { val index = pieces.binarySearch { (range, _) -> when { arg >= range.endInclusive -> -1 @@ -74,7 +74,7 @@ private class OrderedPiecewisePolynomial>( */ public class PiecewiseBuilder>(delimiter: T) { private val delimiters: MutableList = arrayListOf(delimiter) - private val pieces: MutableList> = arrayListOf() + private val pieces: MutableList> = arrayListOf() /** * Dynamically adds a piece to the right side (beyond maximum argument value of previous piece) @@ -82,7 +82,7 @@ public class PiecewiseBuilder>(delimiter: T) { * @param right new rightmost position. If is less than current rightmost position, an error is thrown. * @param piece the sub-function. */ - public fun putRight(right: T, piece: Polynomial) { + public fun putRight(right: T, piece: ListPolynomial) { require(right > delimiters.last()) { "New delimiter should be to the right of old one" } delimiters += right pieces += piece @@ -94,7 +94,7 @@ public class PiecewiseBuilder>(delimiter: T) { * @param left the new leftmost position. If is less than current rightmost position, an error is thrown. * @param piece the sub-function. */ - public fun putLeft(left: T, piece: Polynomial) { + public fun putLeft(left: T, piece: ListPolynomial) { require(left < delimiters.first()) { "New delimiter should be to the left of old one" } delimiters.add(0, left) pieces.add(0, piece) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index d6c959fd1..b26a57a34 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -6,486 +6,384 @@ package space.kscience.kmath.functions import space.kscience.kmath.operations.* -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract -import kotlin.experimental.ExperimentalTypeInference +import kotlin.js.JsName import kotlin.jvm.JvmName -import kotlin.math.max -import kotlin.math.min + /** - * Polynomial model without fixation on specific context they are applied to. - * - * @param coefficients constant is the leftmost coefficient. + * Abstraction of polynomials. */ -public data class Polynomial( +public interface Polynomial + +/** + * 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") +public interface PolynomialSpace> : Ring

{ /** - * List that collects coefficients of the polynomial. Every monomial `a x^d` is represented as a coefficients - * `a` placed into the list with index `d`. For example coefficients of 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 recommended not to put extra zeros at end of the list (as for `0x^3` and `0x^4` in the example), but is not - * prohibited. + * Returns sum of the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. */ - public val coefficients: List -) : AbstractPolynomial { - override fun toString(): String = "Polynomial$coefficients" -} + public operator fun C.plus(other: Int): C + /** + * Returns difference between the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. + */ + public operator fun C.minus(other: Int): C + /** + * Returns product of the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + public operator fun C.times(other: Int): C -/** - * Returns a [Polynomial] instance with given [coefficients]. The collection of coefficients will be reversed if - * [reverse] parameter is true. - */ -@Suppress("FunctionName") -public fun Polynomial(coefficients: List, reverse: Boolean = false): Polynomial = - Polynomial(with(coefficients) { if (reverse) reversed() else this }) + /** + * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. + */ + public operator fun Int.plus(other: C): C + /** + * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. + */ + public operator fun Int.minus(other: C): C + /** + * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + public operator fun Int.times(other: C): C -/** - * Returns a [Polynomial] instance with given [coefficients]. The collection of coefficients will be reversed if - * [reverse] parameter is true. - */ -@Suppress("FunctionName") -public fun Polynomial(vararg coefficients: C, reverse: Boolean = false): Polynomial = - Polynomial(with(coefficients) { if (reverse) reversed() else toList() }) - -public fun C.asPolynomial() : Polynomial = Polynomial(listOf(this)) - -/** - * Space of univariate 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 open class PolynomialSpace>( - public override val ring: A, -) : AbstractPolynomialSpaceOverRing, A> { /** * Returns sum of the polynomial and the integer represented as polynomial. * * The operation is equivalent to adding [other] copies of unit polynomial to [this]. */ - public override operator fun Polynomial.plus(other: Int): Polynomial = - if (other == 0) this - else - Polynomial( - coefficients - .toMutableList() - .apply { - val result = getOrElse(0) { constantZero } + other - val isResultZero = result.isZero() - - when { - size == 0 && !isResultZero -> add(result) - size > 1 || !isResultZero -> this[0] = result - else -> clear() - } - } - ) + public operator fun P.plus(other: Int): P = addMultipliedBySquaring(this, one, other) /** * Returns difference between the polynomial and the integer represented as polynomial. * * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. */ - public override operator fun Polynomial.minus(other: Int): Polynomial = - if (other == 0) this - else - Polynomial( - coefficients - .toMutableList() - .apply { - val result = getOrElse(0) { constantZero } - other - val isResultZero = result.isZero() - - when { - size == 0 && !isResultZero -> add(result) - size > 1 || !isResultZero -> this[0] = result - else -> clear() - } - } - ) + public operator fun P.minus(other: Int): P = addMultipliedBySquaring(this, one, -other) /** * Returns product of the polynomial and the integer represented as polynomial. * * The operation is equivalent to sum of [other] copies of [this]. */ - public override operator fun Polynomial.times(other: Int): Polynomial = - if (other == 0) zero - else Polynomial( - coefficients - .applyAndRemoveZeros { - for (deg in indices) this[deg] = this[deg] * other - } - ) + public operator fun P.times(other: Int): P = multiplyBySquaring(this, other) /** * Returns sum of the integer represented as polynomial and the polynomial. * * The operation is equivalent to adding [this] copies of unit polynomial to [other]. */ - public override operator fun Int.plus(other: Polynomial): Polynomial = - if (this == 0) other - else - Polynomial( - other.coefficients - .toMutableList() - .apply { - val result = this@plus + getOrElse(0) { constantZero } - val isResultZero = result.isZero() - - when { - size == 0 && !isResultZero -> add(result) - size > 1 || !isResultZero -> this[0] = result - else -> clear() - } - } - ) + public operator fun Int.plus(other: P): P = addMultipliedBySquaring(other, one, this) /** * Returns difference between the integer represented as polynomial and the polynomial. * * The operation is equivalent to subtraction [this] copies of unit polynomial from [other]. */ - public override operator fun Int.minus(other: Polynomial): Polynomial = - if (this == 0) other - else - Polynomial( - other.coefficients - .toMutableList() - .apply { - forEachIndexed { index, c -> if (index != 0) this[index] = -c } - - val result = this@minus - getOrElse(0) { constantZero } - val isResultZero = result.isZero() - - when { - size == 0 && !isResultZero -> add(result) - size > 1 || !isResultZero -> this[0] = result - else -> clear() - } - } - ) + public operator fun Int.minus(other: P): P = addMultipliedBySquaring(-other, one, this) /** * Returns product of the integer represented as polynomial and the polynomial. * * The operation is equivalent to sum of [this] copies of [other]. */ - public override operator fun Int.times(other: Polynomial): Polynomial = - if (this == 0) zero - else Polynomial( - other.coefficients - .applyAndRemoveZeros { - for (deg in indices) this[deg] = this@times * this[deg] - } - ) + public operator fun Int.times(other: P): P = multiplyBySquaring(other, this) + + /** + * Returns the same constant. + */ + @JvmName("constantUnaryPlus") + @JsName("constantUnaryPlus") + public operator fun C.unaryPlus(): C = this + /** + * Returns negation of the constant. + */ + @JvmName("constantUnaryMinus") + @JsName("constantUnaryMinus") + public operator fun C.unaryMinus(): C + /** + * Returns sum of the constants. + */ + @JvmName("constantPlus") + @JsName("constantPlus") + public operator fun C.plus(other: C): C + /** + * Returns difference of the constants. + */ + @JvmName("constantMinus") + @JsName("constantMinus") + public operator fun C.minus(other: C): C + /** + * Returns product of the constants. + */ + @JvmName("constantTimes") + @JsName("constantTimes") + public operator fun C.times(other: C): C + /** + * Raises [arg] to the integer power [exponent]. + */ + @JvmName("constantPower") + @JsName("constantPower") + public fun power(arg: C, exponent: UInt) : C + + /** + * Check if the instant is zero constant. + */ + public fun C.isZero(): Boolean = this == constantZero + /** + * Check if the instant is NOT zero constant. + */ + public fun C.isNotZero(): Boolean = !isZero() + /** + * Check if the instant is unit constant. + */ + public fun C.isOne(): Boolean = this == constantOne + /** + * Check if the instant is NOT unit constant. + */ + public fun C.isNotOne(): Boolean = !isOne() + /** + * Check if the instant is minus unit constant. + */ + public fun C.isMinusOne(): Boolean = this == -constantOne + /** + * Check if the instant is NOT minus unit constant. + */ + public fun C.isNotMinusOne(): Boolean = !isMinusOne() + + /** + * 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 polynomial and the polynomial. */ - public override operator fun C.plus(other: Polynomial): Polynomial = - if (this.isZero()) other - else with(other.coefficients) { - if (isEmpty()) Polynomial(listOf(this@plus)) - else Polynomial( - toMutableList() - .apply { - val result = if (size == 0) this@plus else this@plus + get(0) - val isResultZero = result.isZero() - - when { - size == 0 && !isResultZero -> add(result) - size > 1 || !isResultZero -> this[0] = result - else -> clear() - } - } - ) - } + public operator fun C.plus(other: P): P /** * Returns difference between the constant represented as polynomial and the polynomial. */ - public override operator fun C.minus(other: Polynomial): Polynomial = - if (this.isZero()) other - else with(other.coefficients) { - if (isEmpty()) Polynomial(listOf(this@minus)) - else Polynomial( - toMutableList() - .apply { - forEachIndexed { index, c -> if (index != 0) this[index] = -c } - - val result = if (size == 0) this@minus else this@minus - get(0) - val isResultZero = result.isZero() - - when { - size == 0 && !isResultZero -> add(result) - size > 1 || !isResultZero -> this[0] = result - else -> clear() - } - } - ) - } + public operator fun C.minus(other: P): P /** * Returns product of the constant represented as polynomial and the polynomial. */ - public override operator fun C.times(other: Polynomial): Polynomial = - if (this.isZero()) other - else Polynomial( - other.coefficients - .applyAndRemoveZeros { - for (deg in indices) this[deg] = this@times * this[deg] - } - ) + public operator fun C.times(other: P): P /** * Returns sum of the constant represented as polynomial and the polynomial. */ - public override operator fun Polynomial.plus(other: C): Polynomial = - if (other.isZero()) this - else with(coefficients) { - if (isEmpty()) Polynomial(listOf(other)) - else Polynomial( - toMutableList() - .apply { - val result = if (size == 0) other else get(0) + other - val isResultZero = result.isZero() - - when { - size == 0 && !isResultZero -> add(result) - size > 1 || !isResultZero -> this[0] = result - else -> clear() - } - } - ) - } + public operator fun P.plus(other: C): P /** * Returns difference between the constant represented as polynomial and the polynomial. */ - public override operator fun Polynomial.minus(other: C): Polynomial = - if (other.isZero()) this - else with(coefficients) { - if (isEmpty()) Polynomial(listOf(-other)) - else Polynomial( - toMutableList() - .apply { - val result = if (size == 0) other else get(0) - other - val isResultZero = result.isZero() - - when { - size == 0 && !isResultZero -> add(result) - size > 1 || !isResultZero -> this[0] = result - else -> clear() - } - } - ) - } + public operator fun P.minus(other: C): P /** * Returns product of the constant represented as polynomial and the polynomial. */ - public override operator fun Polynomial.times(other: C): Polynomial = - if (other.isZero()) this - else Polynomial( - coefficients - .applyAndRemoveZeros { - for (deg in indices) this[deg] = this[deg] * other - } - ) + public operator fun P.times(other: C): P + /** + * Returns the same polynomial. + */ + public override operator fun P.unaryPlus(): P = this /** * Returns negation of the polynomial. */ - public override operator fun Polynomial.unaryMinus(): Polynomial = - Polynomial(coefficients.map { -it }) + public override operator fun P.unaryMinus(): P /** * Returns sum of the polynomials. */ - public override operator fun Polynomial.plus(other: Polynomial): Polynomial { - val thisDegree = degree - val otherDegree = other.degree - return Polynomial( - Coefficients(max(thisDegree, otherDegree) + 1) { - when { - it > thisDegree -> other.coefficients[it] - it > otherDegree -> coefficients[it] - else -> coefficients[it] + other.coefficients[it] - } - } - ) - } + public override operator fun P.plus(other: P): P /** * Returns difference of the polynomials. */ - public override operator fun Polynomial.minus(other: Polynomial): Polynomial { - val thisDegree = degree - val otherDegree = other.degree - return Polynomial( - Coefficients(max(thisDegree, otherDegree) + 1) { - when { - it > thisDegree -> -other.coefficients[it] - it > otherDegree -> coefficients[it] - else -> coefficients[it] - other.coefficients[it] - } - } - ) - } + public override operator fun P.minus(other: P): P /** * Returns product of the polynomials. */ - public override operator fun Polynomial.times(other: Polynomial): Polynomial { - val thisDegree = degree - val otherDegree = other.degree - return when { - thisDegree == -1 -> zero - otherDegree == -1 -> zero - else -> - Polynomial( - Coefficients(thisDegree + otherDegree + 1) { d -> - (max(0, d - otherDegree)..min(thisDegree, d)) - .map { coefficients[it] * other.coefficients[d - it] } - .reduce { acc, rational -> acc + rational } - } - ) - } - } + 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 = exponentiationBySquaring(arg, exponent) /** * Check if the instant is zero polynomial. */ - public override fun Polynomial.isZero(): Boolean = coefficients.all { it.isZero() } + public fun P.isZero(): Boolean = this equalsTo zero + /** + * Check if the instant is NOT zero polynomial. + */ + public fun P.isNotZero(): Boolean = !isZero() /** * Check if the instant is unit polynomial. */ - public override fun Polynomial.isOne(): Boolean = - with(coefficients) { - isNotEmpty() && withIndex().all { (index, c) -> if (index == 0) c.isOne() else c.isZero() } - } + public fun P.isOne(): Boolean = this equalsTo one + /** + * Check if the instant is NOT unit polynomial. + */ + public fun P.isNotOne(): Boolean = !isOne() /** * Check if the instant is minus unit polynomial. */ - public override fun Polynomial.isMinusOne(): Boolean = - with(coefficients) { - isNotEmpty() && withIndex().all { (index, c) -> if (index == 0) c.isMinusOne() else c.isZero() } - } + public fun P.isMinusOne(): Boolean = this equalsTo -one + /** + * Check if the instant is NOT minus unit polynomial. + */ + public fun P.isNotMinusOne(): Boolean = !isMinusOne() /** * Instance of zero polynomial (zero of the polynomial ring). */ - override val zero: Polynomial = Polynomial(emptyList()) + public override val zero: P /** - * Instance of unit constant (unit of the underlying ring). + * Instance of unit polynomial (unit of the polynomial ring). */ - override val one: Polynomial = Polynomial(listOf(constantOne)) + public override val one: P /** * Checks equality of the polynomials. */ - public override infix fun Polynomial.equalsTo(other: Polynomial): Boolean = - when { - this === other -> true - this.degree == other.degree -> (0..degree).all { coefficients[it] == other.coefficients[it] } - else -> false - } + public infix fun P.equalsTo(other: P): Boolean + /** + * Checks NOT equality of the polynomials. + */ + public infix fun P.notEqualsTo(other: P): Boolean = !(this equalsTo other) /** * 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 Polynomial.degree: Int get() = coefficients.indexOfLast { it != constantZero } + public val P.degree: Int + /** + * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. + */ + public fun P.isConstant(): Boolean = degree <= 0 + /** + * Checks if the instant is **not** constant polynomial (of degree no more than 0) over considered ring. + */ + public fun P.isNotConstant(): Boolean = !isConstant() + /** + * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. + */ + public fun P.isNonZeroConstant(): Boolean = degree == 0 + /** + * Checks if the instant is **not** constant non-zero polynomial (of degree no more than 0) over considered ring. + */ + public fun P.isNotNonZeroConstant(): Boolean = !isNonZeroConstant() /** * If polynomial is a constant polynomial represents and returns it as constant. * Otherwise, (when the polynomial is not constant polynomial) returns `null`. */ - public override fun Polynomial.asConstantOrNull(): C? = - with(coefficients) { - when { - isEmpty() -> constantZero - withIndex().all { (index, c) -> index == 0 || c.isZero() } -> first() - else -> null - } - } - - @Suppress("NOTHING_TO_INLINE") - public inline fun Polynomial.substitute(argument: C): C = this.substitute(ring, argument) - @Suppress("NOTHING_TO_INLINE") - public inline fun Polynomial.substitute(argument: Polynomial): Polynomial = this.substitute(ring, argument) - - @Suppress("NOTHING_TO_INLINE") - public inline fun Polynomial.asFunction(): (C) -> C = { this.substitute(ring, it) } - @Suppress("NOTHING_TO_INLINE") - public inline fun Polynomial.asFunctionOnConstants(): (C) -> C = { this.substitute(ring, it) } - @Suppress("NOTHING_TO_INLINE") - public inline fun Polynomial.asFunctionOnPolynomials(): (Polynomial) -> Polynomial = { this.substitute(ring, it) } - + public fun P.asConstantOrNull(): C? /** - * Evaluates the polynomial for the given value [argument]. + * If polynomial is a constant polynomial represents and returns it as constant. + * Otherwise, (when the polynomial is not constant polynomial) raises corresponding exception. */ - @Suppress("NOTHING_TO_INLINE") - public inline operator fun Polynomial.invoke(argument: C): C = this.substitute(ring, argument) - @Suppress("NOTHING_TO_INLINE") - public inline operator fun Polynomial.invoke(argument: Polynomial): Polynomial = this.substitute(ring, argument) + public fun P.asConstant(): C = requireNotNull(asConstantOrNull()) { "Can not represent non-constant polynomial as a constant" } - // TODO: Move to other internal utilities with context receiver - @JvmName("applyAndRemoveZerosInternal") - internal inline fun MutableList.applyAndRemoveZeros(block: MutableList.() -> Unit) : MutableList { - contract { - callsInPlace(block, InvocationKind.EXACTLY_ONCE) - } - block() - while (isNotEmpty() && elementAt(lastIndex).isZero()) removeAt(lastIndex) - return this - } - internal inline fun List.applyAndRemoveZeros(block: MutableList.() -> Unit) : List = - toMutableList().applyAndRemoveZeros(block) - @Suppress("FunctionName") - internal inline fun MutableCoefficients(size: Int, init: (index: Int) -> C): MutableList { - val list = ArrayList(size) - repeat(size) { index -> list.add(init(index)) } - with(list) { while (isNotEmpty() && elementAt(lastIndex).isZero()) removeAt(lastIndex) } - return list - } - @Suppress("FunctionName") - internal inline fun Coefficients(size: Int, init: (index: Int) -> C): List = MutableCoefficients(size, init) - @OptIn(ExperimentalTypeInference::class) - internal inline fun buildCoefficients(@BuilderInference builderAction: MutableList.() -> Unit): List { - contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } - return buildList { - builderAction() - while (isNotEmpty() && elementAt(lastIndex).isZero()) removeAt(lastIndex) - } - } - @OptIn(ExperimentalTypeInference::class) - internal inline fun buildCoefficients(capacity: Int, @BuilderInference builderAction: MutableList.() -> Unit): List { - contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } - return buildList(capacity) { - builderAction() - while (isNotEmpty() && elementAt(lastIndex).isZero()) removeAt(lastIndex) - } - } + override fun add(left: P, right: P): P = left + right + override fun multiply(left: P, right: P): P = left * right } /** - * Space of polynomials constructed over ring. + * 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 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]. + * @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. */ -public class ScalablePolynomialSpace( - ring: A, -) : PolynomialSpace(ring), ScaleOperations> where A : Ring, A : ScaleOperations { - override fun scale(a: Polynomial, value: Double): Polynomial = - ring { Polynomial(a.coefficients.map { scale(it, value) }) } -} +@Suppress("INAPPLICABLE_JVM_NAME") +public interface PolynomialSpaceOverRing, A: Ring> : PolynomialSpace { + + public val ring: A + + /** + * Returns sum of the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. + */ + public override operator fun C.plus(other: Int): C = ring { addMultipliedBySquaring(this@plus, one, other) } + /** + * Returns difference between the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. + */ + public override operator fun C.minus(other: Int): C = ring { addMultipliedBySquaring(this@minus, one, -other) } + /** + * Returns product of the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + public override operator fun C.times(other: Int): C = ring { multiplyBySquaring(this@times, other) } + + /** + * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. + */ + public override operator fun Int.plus(other: C): C = ring { addMultipliedBySquaring(other, one, this@plus) } + /** + * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. + */ + public override operator fun Int.minus(other: C): C = ring { addMultipliedBySquaring(-other, one, this@minus) } + /** + * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + public override operator fun Int.times(other: C): C = ring { multiplyBySquaring(other, this@times) } + + /** + * Returns negation of the constant. + */ + @JvmName("constantUnaryMinus") + public override operator fun C.unaryMinus(): C = ring { -this@unaryMinus } + /** + * Returns sum of the constants. + */ + @JvmName("constantPlus") + public override operator fun C.plus(other: C): C = ring { this@plus + other } + /** + * Returns difference of the constants. + */ + @JvmName("constantMinus") + public override operator fun C.minus(other: C): C = ring { this@minus - other } + /** + * Returns product of the constants. + */ + @JvmName("constantTimes") + public override operator fun C.times(other: C): C = ring { this@times * other } + /** + * Raises [arg] to the integer power [exponent]. + */ + @JvmName("constantPower") + 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 +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index 51c1e2f80..635661b8a 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -5,150 +5,1081 @@ package space.kscience.kmath.functions -import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.* +import kotlin.js.JsName +import kotlin.jvm.JvmName -public data class RationalFunction internal constructor ( - public override val numerator: Polynomial, - public override val denominator: Polynomial -) : AbstractRationalFunction> { - override fun toString(): String = "RationalFunction${numerator.coefficients}/${denominator.coefficients}" +/** + * 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 } -// Waiting for context receivers :( TODO: Replace with context receivers when they will be available +/** + * 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 in them. + * @param R the type of rational functions. + */ // TODO: Add support of field +@Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") +public interface RationalFunctionalSpace, R: RationalFunction> : Ring { + /** + * Returns sum of the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. + */ + public operator fun C.plus(other: Int): C + /** + * Returns difference between the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. + */ + public operator fun C.minus(other: Int): C + /** + * Returns product of the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + public operator fun C.times(other: Int): C -//context(RationalFunctionSpace) -//@Suppress("FunctionName") -//internal fun > RationalFunction(numerator: Polynomial, denominator: Polynomial): RationalFunction = -// if (denominator.isZero()) throw ArithmeticException("/ by zero") -// else RationalFunction(numerator, denominator) -//context(RationalFunctionSpace) -//@Suppress("FunctionName") -//public fun > RationalFunction(numeratorCoefficients: List, denominatorCoefficients: List, reverse: Boolean = false): RationalFunction = -// RationalFunction( -// Polynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), -// Polynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } ).also { if (it.isZero()) } -// ) -//context(RationalFunctionSpace) -//@Suppress("FunctionName") -//public fun > RationalFunction(numerator: Polynomial): RationalFunction = -// RationalFunction(numerator, onePolynomial) -//context(RationalFunctionSpace) -//@Suppress("FunctionName") -//public fun > RationalFunction(numeratorCoefficients: List, reverse: Boolean = false): RationalFunction = -// RationalFunction( -// Polynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ) -// ) + /** + * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. + */ + public operator fun Int.plus(other: C): C + /** + * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. + */ + public operator fun Int.minus(other: C): C + /** + * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + public operator fun Int.times(other: C): C -public class RationalFunctionSpace> ( - public val ring: A, -) : - AbstractRationalFunctionalSpaceOverPolynomialSpace< - C, - Polynomial, - RationalFunction, - PolynomialSpace, - >, - PolynomialSpaceOfFractions< - C, - Polynomial, - RationalFunction, - >() { + /** + * Returns sum of the constant and the integer represented as polynomial. + * + * The operation is equivalent to adding [other] copies of unit polynomial to [this]. + */ + public operator fun P.plus(other: Int): P + /** + * Returns difference between the constant and the integer represented as polynomial. + * + * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. + */ + public operator fun P.minus(other: Int): P + /** + * Returns product of the constant and the integer represented as polynomial. + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + public operator fun P.times(other: Int): P - override val polynomialRing : PolynomialSpace = PolynomialSpace(ring) - override fun constructRationalFunction(numerator: Polynomial, denominator: Polynomial): RationalFunction = - RationalFunction(numerator, denominator) + /** + * Returns sum of the integer represented as polynomial and the constant. + * + * The operation is equivalent to adding [this] copies of unit polynomial to [other]. + */ + public operator fun Int.plus(other: P): P + /** + * Returns difference between the integer represented as polynomial and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit polynomial from [other]. + */ + public operator fun Int.minus(other: P): P + /** + * Returns product of the integer represented as polynomial and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + public operator fun Int.times(other: P): P + + /** + * Returns sum of the rational function and the integer represented as rational function. + * + * The operation is equivalent to adding [other] copies of unit polynomial to [this]. + */ + public operator fun R.plus(other: Int): R = addMultipliedBySquaring(this, one, other) + /** + * Returns difference between the rational function and the integer represented as rational function. + * + * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. + */ + public operator fun R.minus(other: Int): R = addMultipliedBySquaring(this, one, -other) + /** + * Returns product of the rational function and the integer represented as rational function. + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + public operator fun R.times(other: Int): R = multiplyBySquaring(this, other) + + /** + * Returns sum of the integer represented as 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 = addMultipliedBySquaring(other, one, this) + /** + * Returns difference between the integer represented as 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 = addMultipliedBySquaring(-other, one, this) + /** + * Returns product of the integer represented as 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 = multiplyBySquaring(other, this) + + /** + * Returns the same constant. + */ + @JvmName("constantUnaryPlus") + @JsName("constantUnaryPlus") + public operator fun C.unaryPlus(): C = this + /** + * Returns negation of the constant. + */ + @JvmName("constantUnaryMinus") + @JsName("constantUnaryMinus") + public operator fun C.unaryMinus(): C + /** + * Returns sum of the constants. + */ + @JvmName("constantPlus") + @JsName("constantPlus") + public operator fun C.plus(other: C): C + /** + * Returns difference of the constants. + */ + @JvmName("constantMinus") + @JsName("constantMinus") + public operator fun C.minus(other: C): C + /** + * Returns product of the constants. + */ + @JvmName("constantTimes") + @JsName("constantTimes") + public operator fun C.times(other: C): C + /** + * Raises [arg] to the integer power [exponent]. + */ + @JvmName("constantPower") + @JsName("constantPower") + public fun power(arg: C, exponent: UInt) : C + + /** + * Check if the instant is zero constant. + */ + public fun C.isZero(): Boolean = this == constantZero + /** + * Check if the instant is NOT zero constant. + */ + public fun C.isNotZero(): Boolean = !isZero() + /** + * Check if the instant is unit constant. + */ + public fun C.isOne(): Boolean = this == constantOne + /** + * Check if the instant is NOT unit constant. + */ + public fun C.isNotOne(): Boolean = !isOne() + /** + * Check if the instant is minus unit constant. + */ + public fun C.isMinusOne(): Boolean = this == -constantOne + /** + * Check if the instant is NOT minus unit constant. + */ + public fun C.isNotMinusOne(): Boolean = !isMinusOne() + + /** + * 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 polynomial and the polynomial. + */ + public operator fun C.plus(other: P): P + /** + * Returns difference between the constant represented as polynomial and the polynomial. + */ + public operator fun C.minus(other: P): P + /** + * Returns product of the constant represented as polynomial and the polynomial. + */ + public operator fun C.times(other: P): P + + /** + * Returns sum of the constant represented as polynomial and the polynomial. + */ + public operator fun P.plus(other: C): P + /** + * Returns difference between the constant represented as polynomial and the polynomial. + */ + public operator fun P.minus(other: C): P + /** + * Returns product of the constant represented as polynomial and the polynomial. + */ + public operator fun P.times(other: C): P + + /** + * Returns the same polynomial. + */ + public operator fun P.unaryPlus(): P = this + /** + * Returns negation of the polynomial. + */ + public operator fun P.unaryMinus(): P + /** + * Returns sum of the polynomials. + */ + public operator fun P.plus(other: P): P + /** + * Returns difference of the polynomials. + */ + public operator fun P.minus(other: P): P + /** + * Returns product of the polynomials. + */ + public operator fun P.times(other: P): P + /** + * Raises [arg] to the integer power [exponent]. + */ + public fun power(arg: P, exponent: UInt) : P + + /** + * Check if the instant is zero polynomial. + */ + public fun P.isZero(): Boolean = this equalsTo polynomialZero + /** + * Check if the instant is NOT zero polynomial. + */ + public fun P.isNotZero(): Boolean = !isZero() + /** + * Check if the instant is unit polynomial. + */ + public fun P.isOne(): Boolean = this equalsTo polynomialOne + /** + * Check if the instant is NOT unit polynomial. + */ + public fun P.isNotOne(): Boolean = !isOne() + /** + * Check if the instant is minus unit polynomial. + */ + public fun P.isMinusOne(): Boolean = this equalsTo -polynomialOne + /** + * Check if the instant is NOT minus unit polynomial. + */ + public fun P.isNotMinusOne(): Boolean = !isMinusOne() + + /** + * 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 + + /** + * Checks equality of the polynomials. + */ + public infix fun P.equalsTo(other: P): Boolean + /** + * Checks NOT equality of the polynomials. + */ + public infix fun P.notEqualsTo(other: P): Boolean = !(this equalsTo other) + + /** + * Returns sum of the constant represented as rational function and the rational function. + */ + public operator fun C.plus(other: R): R + /** + * Returns difference between the constant represented as polynomial and the rational function. + */ + public operator fun C.minus(other: R): R + /** + * Returns product of the constant represented as polynomial and the rational function. + */ + public operator fun C.times(other: R): R + + /** + * Returns sum of the constant represented as rational function and the rational function. + */ + public operator fun R.plus(other: C): R + /** + * Returns difference between the constant represented as rational function and the rational function. + */ + public operator fun R.minus(other: C): R + /** + * Returns product of the constant represented as rational function and the rational function. + */ + public operator fun R.times(other: C): R + + /** + * Returns sum of the polynomial represented as rational function and the rational function. + */ + public operator fun P.plus(other: R): R + /** + * Returns difference between the polynomial represented as polynomial and the rational function. + */ + public operator fun P.minus(other: R): R + /** + * Returns product of the polynomial represented as polynomial and the rational function. + */ + public operator fun P.times(other: R): R + + /** + * Returns sum of the polynomial represented as rational function and the rational function. + */ + public operator fun R.plus(other: P): R + /** + * Returns difference between the polynomial represented as rational function and the rational function. + */ + public operator fun R.minus(other: P): R + /** + * Returns product of the polynomial represented as rational function and the rational function. + */ + public operator fun R.times(other: P): R + + /** + * 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 + /** + * Raises [arg] to the integer power [exponent]. + */ + public override fun power(arg: R, exponent: UInt) : R = exponentiationBySquaring(arg, exponent) + + /** + * Check if the instant is zero rational function. + */ + public fun R.isZero(): Boolean = numerator equalsTo polynomialZero + /** + * Check if the instant is NOT zero rational function. + */ + public fun R.isNotZero(): Boolean = !isZero() + /** + * Check if the instant is unit rational function. + */ + public fun R.isOne(): Boolean = numerator equalsTo denominator + /** + * Check if the instant is NOT unit rational function. + */ + public fun R.isNotOne(): Boolean = !isOne() + /** + * Check if the instant is minus unit rational function. + */ + public fun R.isMinusOne(): Boolean = (numerator + denominator).isZero() + /** + * Check if the instant is NOT minus unit rational function. + */ + public fun R.isNotMinusOne(): Boolean = !isMinusOne() /** * Instance of zero rational function (zero of the rational functions ring). */ - public override val zero: RationalFunction = RationalFunction(polynomialZero, polynomialOne) + public override val zero: R /** * Instance of unit polynomial (unit of the rational functions ring). */ - public override val one: RationalFunction = RationalFunction(polynomialOne, polynomialOne) + public override val one: R - // TODO: Разобрать + /** + * Checks equality of the rational functions. + */ + public infix fun R.equalsTo(other: R): Boolean = + when { + this === other -> true + numerator.isZero() != other.numerator.isZero() -> false + numeratorDegree - denominatorDegree != with(other) { numeratorDegree - denominatorDegree } -> false + else -> numerator * other.denominator equalsTo other.numerator * denominator + } + /** + * Checks NOT equality of the polynomials. + */ + public infix fun R.notEqualsTo(other: R): Boolean = !(this equalsTo other) - public operator fun RationalFunction.div(other: RationalFunction): RationalFunction = - RationalFunction( - numerator * other.denominator, - denominator * other.numerator + /** + * 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 + + /** + * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. + */ + public fun P.isConstant(): Boolean = degree <= 0 + /** + * Checks if the instant is **not** constant polynomial (of degree no more than 0) over considered ring. + */ + public fun P.isNotConstant(): Boolean = !isConstant() + /** + * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. + */ + public fun P.isNonZeroConstant(): Boolean = degree == 0 + /** + * Checks if the instant is **not** constant non-zero polynomial (of degree no more than 0) over considered ring. + */ + public fun P.isNotNonZeroConstant(): Boolean = !isNonZeroConstant() + /** + * If polynomial is a constant polynomial represents and returns it as constant. + * Otherwise, (when the polynomial is not constant polynomial) returns `null`. + */ + public fun P.asConstantOrNull(): C? + /** + * If polynomial is a constant polynomial represents and returns it as constant. + * Otherwise, (when the polynomial is not constant polynomial) raises corresponding exception. + */ + public fun P.asConstant(): C = requireNotNull(asConstantOrNull()) { "Can not represent non-constant polynomial as a constant" } + + /** + * 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. + */ // TODO: Add support of field +@Suppress("INAPPLICABLE_JVM_NAME") +public interface RationalFunctionalSpaceOverRing, R: RationalFunction, A: Ring> : RationalFunctionalSpace { + + public val ring: A + + /** + * Returns sum of the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. + */ + public override operator fun C.plus(other: Int): C = ring { addMultipliedBySquaring(this@plus, one, other) } + /** + * Returns difference between the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. + */ + public override operator fun C.minus(other: Int): C = ring { addMultipliedBySquaring(this@minus, one, -other) } + /** + * Returns product of the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + public override operator fun C.times(other: Int): C = ring { multiplyBySquaring(this@times, other) } + + /** + * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. + */ + public override operator fun Int.plus(other: C): C = ring { addMultipliedBySquaring(other, one, this@plus) } + /** + * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. + */ + public override operator fun Int.minus(other: C): C = ring { addMultipliedBySquaring(-other, one, this@minus) } + /** + * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + public override operator fun Int.times(other: C): C = ring { multiplyBySquaring(other, this@times) } + + /** + * Returns the same constant. + */ + @JvmName("constantUnaryPlus") + public override operator fun C.unaryPlus(): C = ring { +this@unaryPlus } + /** + * Returns negation of the constant. + */ + @JvmName("constantUnaryMinus") + public override operator fun C.unaryMinus(): C = ring { -this@unaryMinus } + /** + * Returns sum of the constants. + */ + @JvmName("constantPlus") + public override operator fun C.plus(other: C): C = ring { this@plus + other } + /** + * Returns difference of the constants. + */ + @JvmName("constantMinus") + public override operator fun C.minus(other: C): C = ring { this@minus - other } + /** + * Returns product of the constants. + */ + @JvmName("constantTimes") + public override operator fun C.times(other: C): C = ring { this@times * other } + /** + * Raises [arg] to the integer power [exponent]. + */ + @JvmName("constantPower") + 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. + */ // TODO: Add support of field +@Suppress("INAPPLICABLE_JVM_NAME") +public interface RationalFunctionalSpaceOverPolynomialSpace< + C, + P: Polynomial, + R: RationalFunction, + AP: PolynomialSpace, + > : RationalFunctionalSpace { + + public val polynomialRing: AP + + /** + * Returns sum of the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. + */ + public override operator fun C.plus(other: Int): C = polynomialRing { this@plus + other } + /** + * Returns difference between the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. + */ + public override operator fun C.minus(other: Int): C = polynomialRing { this@minus - other } + /** + * Returns product of the constant and the integer represented as constant (member of underlying ring). + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + public override operator fun C.times(other: Int): C = polynomialRing { this@times * other } + + /** + * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. + */ + public override operator fun Int.plus(other: C): C = polynomialRing { this@plus + other } + /** + * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. + */ + public override operator fun Int.minus(other: C): C = polynomialRing { this@minus - other } + /** + * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + public override operator fun Int.times(other: C): C = polynomialRing { this@times * other } + + /** + * Returns sum of the constant and the integer represented as polynomial. + * + * The operation is equivalent to adding [other] copies of unit polynomial to [this]. + */ + public override operator fun P.plus(other: Int): P = polynomialRing { this@plus + other } + /** + * Returns difference between the constant and the integer represented as polynomial. + * + * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. + */ + public override operator fun P.minus(other: Int): P = polynomialRing { this@minus - other } + /** + * Returns product of the constant and the integer represented as polynomial. + * + * The operation is equivalent to sum of [other] copies of [this]. + */ + public override operator fun P.times(other: Int): P = polynomialRing { this@times * other } + + /** + * Returns sum of the integer represented as polynomial and the constant. + * + * The operation is equivalent to adding [this] copies of unit polynomial to [other]. + */ + public override operator fun Int.plus(other: P): P = polynomialRing { this@plus + other } + /** + * Returns difference between the integer represented as polynomial and the constant. + * + * The operation is equivalent to subtraction [this] copies of unit polynomial from [other]. + */ + public override operator fun Int.minus(other: P): P = polynomialRing { this@minus - other } + /** + * Returns product of the integer represented as polynomial and the constant. + * + * The operation is equivalent to sum of [this] copies of [other]. + */ + public override operator fun Int.times(other: P): P = polynomialRing { this@times * other } + + /** + * Returns the same constant. + */ + @JvmName("constantUnaryPlus") + public override operator fun C.unaryPlus(): C = polynomialRing { +this@unaryPlus } + /** + * Returns negation of the constant. + */ + @JvmName("constantUnaryMinus") + public override operator fun C.unaryMinus(): C = polynomialRing { -this@unaryMinus } + /** + * Returns sum of the constants. + */ + @JvmName("constantPlus") + public override operator fun C.plus(other: C): C = polynomialRing { this@plus + other } + /** + * Returns difference of the constants. + */ + @JvmName("constantMinus") + public override operator fun C.minus(other: C): C = polynomialRing { this@minus - other } + /** + * Returns product of the constants. + */ + @JvmName("constantTimes") + public override operator fun C.times(other: C): C = polynomialRing { this@times * other } + /** + * Raises [arg] to the integer power [exponent]. + */ + @JvmName("constantPower") + public override fun power(arg: C, exponent: UInt) : C = polynomialRing { power(arg, exponent) } + + /** + * Check if the instant is zero constant. + */ + public override fun C.isZero(): Boolean = polynomialRing { this@isZero.isZero() } + /** + * Check if the instant is NOT zero constant. + */ + public override fun C.isNotZero(): Boolean = polynomialRing { this@isNotZero.isNotZero() } + /** + * Check if the instant is unit constant. + */ + public override fun C.isOne(): Boolean = polynomialRing { this@isOne.isOne() } + /** + * Check if the instant is NOT unit constant. + */ + public override fun C.isNotOne(): Boolean = polynomialRing { this@isNotOne.isNotOne() } + /** + * Check if the instant is minus unit constant. + */ + public override fun C.isMinusOne(): Boolean = polynomialRing { this@isMinusOne.isMinusOne() } + /** + * Check if the instant is NOT minus unit constant. + */ + public override fun C.isNotMinusOne(): Boolean = polynomialRing { this@isNotMinusOne.isNotMinusOne() } + + /** + * 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 polynomial and the polynomial. + */ + public override operator fun C.plus(other: P): P = polynomialRing { this@plus + other } + /** + * Returns difference between the constant represented as polynomial and the polynomial. + */ + public override operator fun C.minus(other: P): P = polynomialRing { this@minus - other } + /** + * Returns product of the constant represented as polynomial and the polynomial. + */ + public override operator fun C.times(other: P): P = polynomialRing { this@times * other } + + /** + * Returns sum of the constant represented as polynomial and the polynomial. + */ + public override operator fun P.plus(other: C): P = polynomialRing { this@plus + other } + /** + * Returns difference between the constant represented as polynomial and the polynomial. + */ + public override operator fun P.minus(other: C): P = polynomialRing { this@minus - other } + /** + * Returns product of the constant represented as polynomial and the polynomial. + */ + public override operator fun P.times(other: C): P = polynomialRing { this@times * other } + + /** + * Returns the same polynomial. + */ + public override operator fun P.unaryPlus(): P = polynomialRing { +this@unaryPlus } + /** + * Returns negation of the polynomial. + */ + public override operator fun P.unaryMinus(): P = polynomialRing { -this@unaryMinus } + /** + * Returns sum of the polynomials. + */ + public override operator fun P.plus(other: P): P = polynomialRing { this@plus + other } + /** + * Returns difference of the polynomials. + */ + public override operator fun P.minus(other: P): P = polynomialRing { this@minus - other } + /** + * Returns product of the polynomials. + */ + public override operator fun P.times(other: P): P = polynomialRing { this@times * other } + /** + * Raises [arg] to the integer power [exponent]. + */ + public override fun power(arg: P, exponent: UInt) : P = polynomialRing { power(arg, exponent) } + + /** + * Check if the instant is zero polynomial. + */ + public override fun P.isZero(): Boolean = polynomialRing { this@isZero.isZero() } + /** + * Check if the instant is NOT zero polynomial. + */ + public override fun P.isNotZero(): Boolean = polynomialRing { this@isNotZero.isNotZero() } + /** + * Check if the instant is unit polynomial. + */ + public override fun P.isOne(): Boolean = polynomialRing { this@isOne.isOne() } + /** + * Check if the instant is NOT unit polynomial. + */ + public override fun P.isNotOne(): Boolean = polynomialRing { this@isNotOne.isNotOne() } + /** + * Check if the instant is minus unit polynomial. + */ + public override fun P.isMinusOne(): Boolean = polynomialRing { this@isMinusOne.isMinusOne() } + /** + * Check if the instant is NOT minus unit polynomial. + */ + public override fun P.isNotMinusOne(): Boolean = polynomialRing { this@isNotMinusOne.isNotMinusOne() } + + /** + * 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 + + /** + * Checks equality of the polynomials. + */ + public override infix fun P.equalsTo(other: P): Boolean = polynomialRing { this@equalsTo equalsTo other } + /** + * Checks NOT equality of the polynomials. + */ + public override infix fun P.notEqualsTo(other: P): Boolean = polynomialRing { this@notEqualsTo notEqualsTo other } + + /** + * 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 } + + /** + * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. + */ + public override fun P.isConstant(): Boolean = polynomialRing { this@isConstant.isConstant() } + /** + * Checks if the instant is **not** constant polynomial (of degree no more than 0) over considered ring. + */ + public override fun P.isNotConstant(): Boolean = polynomialRing { this@isNotConstant.isNotConstant() } + /** + * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. + */ + public override fun P.isNonZeroConstant(): Boolean = polynomialRing { this@isNonZeroConstant.isNonZeroConstant() } + /** + * Checks if the instant is **not** constant non-zero polynomial (of degree no more than 0) over considered ring. + */ + public override fun P.isNotNonZeroConstant(): Boolean = polynomialRing { this@isNotNonZeroConstant.isNotNonZeroConstant() } + /** + * If polynomial is a constant polynomial represents and returns it as constant. + * Otherwise, (when the polynomial is not constant polynomial) returns `null`. + */ + public override fun P.asConstantOrNull(): C? = polynomialRing { this@asConstantOrNull.asConstantOrNull() } + /** + * If polynomial is a constant polynomial represents and returns it as constant. + * Otherwise, (when the polynomial is not constant polynomial) raises corresponding exception. + */ + public override fun P.asConstant(): C = polynomialRing { this@asConstant.asConstant() } +} + +/** + * 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 + * + * @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. + */ // TODO: Add support of field +@Suppress("INAPPLICABLE_JVM_NAME") +public abstract class PolynomialSpaceOfFractions< + C, + P: Polynomial, + R: RationalFunction, + > : RationalFunctionalSpace { + protected abstract fun constructRationalFunction(numerator: P, denominator: P) : R + + /** + * Returns sum of the rational function and the integer represented as 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 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 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 ) - public operator fun RationalFunction.div(other: Polynomial): RationalFunction = - RationalFunction( - numerator, - denominator * other + /** + * Returns sum of the integer represented as 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 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 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 ) - public operator fun RationalFunction.div(other: C): RationalFunction = - RationalFunction( - numerator, - denominator * other + /** + * Returns sum of the constant represented as rational function and the rational function. + */ + public override operator fun C.plus(other: R): R = + constructRationalFunction( + other.denominator * this + other.numerator, + other.denominator + ) + /** + * Returns difference between the constant represented as polynomial and the rational function. + */ + public override operator fun C.minus(other: R): R = + constructRationalFunction( + other.denominator * this - other.numerator, + other.denominator + ) + /** + * Returns product of the constant represented as polynomial and the rational function. + */ + public override operator fun C.times(other: R): R = + constructRationalFunction( + this * other.numerator, + other.denominator ) - public operator fun RationalFunction.div(other: Int): RationalFunction = - RationalFunction( - numerator, - denominator * other + /** + * Returns sum of the constant represented as rational function and the rational function. + */ + public override operator fun R.plus(other: C): R = + constructRationalFunction( + numerator + denominator * other, + denominator + ) + /** + * Returns difference between the constant represented as rational function and the rational function. + */ + public override operator fun R.minus(other: C): R = + constructRationalFunction( + numerator - denominator * other, + denominator + ) + /** + * Returns product of the constant represented as rational function and the rational function. + */ + public override operator fun R.times(other: C): R = + constructRationalFunction( + numerator * other, + denominator ) -// operator fun invoke(arg: UnivariatePolynomial): RationalFunction = -// RationalFunction( -// numerator(arg), -// denominator(arg) -// ) -// -// operator fun invoke(arg: RationalFunction): RationalFunction { -// val num = numerator invokeRFTakeNumerator arg -// val den = denominator invokeRFTakeNumerator arg -// val degreeDif = numeratorDegree - denominatorDegree -// return if (degreeDif > 0) -// RationalFunction( -// num, -// multiplyByPower(den, arg.denominator, degreeDif) -// ) -// else -// RationalFunction( -// multiplyByPower(num, arg.denominator, -degreeDif), -// den -// ) -// } -// -// override fun toString(): String = toString(UnivariatePolynomial.variableName) -// -// fun toString(withVariableName: String = UnivariatePolynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toString(withVariableName) -// else -> "${numerator.toStringWithBrackets(withVariableName)}/${denominator.toStringWithBrackets(withVariableName)}" -// } -// -// fun toStringWithBrackets(withVariableName: String = UnivariatePolynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toStringWithBrackets(withVariableName) -// else -> "(${numerator.toStringWithBrackets(withVariableName)}/${denominator.toStringWithBrackets(withVariableName)})" -// } -// -// fun toReversedString(withVariableName: String = UnivariatePolynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedString(withVariableName) -// else -> "${numerator.toReversedStringWithBrackets(withVariableName)}/${denominator.toReversedStringWithBrackets(withVariableName)}" -// } -// -// fun toReversedStringWithBrackets(withVariableName: String = UnivariatePolynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedStringWithBrackets(withVariableName) -// else -> "(${numerator.toReversedStringWithBrackets(withVariableName)}/${denominator.toReversedStringWithBrackets(withVariableName)})" -// } -// -// fun removeZeros() = -// RationalFunction( -// numerator.removeZeros(), -// denominator.removeZeros() -// ) + /** + * Returns sum of the polynomial represented as rational function and the rational function. + */ + public override operator fun P.plus(other: R): R = + constructRationalFunction( + other.denominator * this + other.numerator, + other.denominator + ) + /** + * Returns difference between the polynomial represented as polynomial and the rational function. + */ + public override operator fun P.minus(other: R): R = + constructRationalFunction( + other.denominator * this - other.numerator, + other.denominator + ) + /** + * Returns product of the polynomial represented as polynomial and the rational function. + */ + public override operator fun P.times(other: R): R = + constructRationalFunction( + this * other.numerator, + other.denominator + ) + + /** + * Returns sum of the polynomial represented as rational function and the rational function. + */ + public override operator fun R.plus(other: P): R = + constructRationalFunction( + numerator + denominator * other, + denominator + ) + /** + * Returns difference between the polynomial represented as rational function and the rational function. + */ + public override operator fun R.minus(other: P): R = + constructRationalFunction( + numerator - denominator * other, + denominator + ) + /** + * Returns product of the polynomial represented as rational function and the rational function. + */ + public override operator fun R.times(other: P): R = + constructRationalFunction( + numerator * other, + denominator + ) + + /** + * 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 + ) + + /** + * Instance of zero rational function (zero of the rational functions ring). + */ + public override val zero: R get() = constructRationalFunction(polynomialZero, polynomialOne) + + /** + * Instance of unit polynomial (unit of the rational functions ring). + */ + public override val one: R get() = constructRationalFunction(polynomialOne, polynomialOne) } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt index d79e8eda3..583160cf4 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt @@ -17,7 +17,7 @@ public fun > A.labeledRationalFunction(): LabeledRationalFunction LabeledRationalFunctionSpace(this) /** - * Creates a [RationalFunctionSpace]'s scope over a received ring. + * Creates a [LabeledRationalFunctionSpace]'s scope over a received ring. */ public inline fun , R> A.labeledRationalFunction(block: LabeledRationalFunctionSpace.() -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt similarity index 72% rename from kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt rename to kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt index afaf27a52..df5ba593a 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt @@ -22,31 +22,31 @@ import kotlin.math.pow // if (degree > -1) Polynomial(coefficients.subList(0, degree + 1)) else zero /** - * Creates a [PolynomialSpace] over a received ring. + * Creates a [ListPolynomialSpace] over a received ring. */ -public fun > A.polynomial(): PolynomialSpace = - PolynomialSpace(this) +public fun > A.listPolynomial(): ListPolynomialSpace = + ListPolynomialSpace(this) /** - * Creates a [PolynomialSpace]'s scope over a received ring. + * Creates a [ListPolynomialSpace]'s scope over a received ring. */ -public inline fun , R> A.polynomial(block: PolynomialSpace.() -> R): R { +public inline fun , R> A.listPolynomial(block: ListPolynomialSpace.() -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return PolynomialSpace(this).block() + return ListPolynomialSpace(this).block() } /** - * Creates a [ScalablePolynomialSpace] over a received scalable ring. + * Creates a [ScalableListPolynomialSpace] over a received scalable ring. */ -public fun A.scalablePolynomial(): ScalablePolynomialSpace where A : Ring, A : ScaleOperations = - ScalablePolynomialSpace(this) +public fun A.scalableListPolynomial(): ScalableListPolynomialSpace where A : Ring, A : ScaleOperations = + ScalableListPolynomialSpace(this) /** - * Creates a [ScalablePolynomialSpace]'s scope over a received scalable ring. + * Creates a [ScalableListPolynomialSpace]'s scope over a received scalable ring. */ -public inline fun A.scalablePolynomial(block: ScalablePolynomialSpace.() -> R): R where A : Ring, A : ScaleOperations { +public inline fun A.scalableListPolynomial(block: ScalableListPolynomialSpace.() -> R): R where A : Ring, A : ScaleOperations { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return ScalablePolynomialSpace(this).block() + return ScalableListPolynomialSpace(this).block() } @Suppress("NOTHING_TO_INLINE") @@ -99,7 +99,7 @@ internal inline fun multiplyAddingTo( /** * Evaluates the value of the given double polynomial for given double argument. */ -public fun Polynomial.substitute(arg: Double): Double = +public fun ListPolynomial.substitute(arg: Double): Double = coefficients.reduceIndexedOrNull { index, acc, c -> acc + c * arg.pow(index) } ?: .0 @@ -109,7 +109,7 @@ public fun Polynomial.substitute(arg: Double): Double = * * It is an implementation of [Horner's method](https://en.wikipedia.org/wiki/Horner%27s_method). */ -public fun Polynomial.substitute(ring: Ring, arg: C): C = ring { +public fun ListPolynomial.substitute(ring: Ring, arg: C): C = ring { if (coefficients.isEmpty()) return@ring zero var result: C = coefficients.last() for (j in coefficients.size - 2 downTo 0) { @@ -118,11 +118,11 @@ public fun Polynomial.substitute(ring: Ring, arg: C): C = ring { return result } -public fun Polynomial.substitute(ring: Ring, arg: Polynomial) : Polynomial = ring { - if (coefficients.isEmpty()) return Polynomial(emptyList()) +public fun ListPolynomial.substitute(ring: Ring, arg: ListPolynomial) : ListPolynomial = ring { + if (coefficients.isEmpty()) return ListPolynomial(emptyList()) val thisDegree = coefficients.indexOfLast { it != zero } - if (thisDegree == -1) return Polynomial(emptyList()) + if (thisDegree == -1) return ListPolynomial(emptyList()) val argDegree = arg.coefficients.indexOfLast { it != zero } if (argDegree == -1) return coefficients[0].asPolynomial() val constantZero = zero @@ -145,27 +145,27 @@ public fun Polynomial.substitute(ring: Ring, arg: Polynomial) : Pol } with(resultCoefs) { while (isNotEmpty() && elementAt(lastIndex) == constantZero) removeAt(lastIndex) } - return Polynomial(resultCoefs) + return ListPolynomial(resultCoefs) } /** * Represent the polynomial as a regular context-less function. */ -public fun > Polynomial.asFunction(ring: A): (C) -> C = { substitute(ring, it) } +public fun > ListPolynomial.asFunction(ring: A): (C) -> C = { substitute(ring, it) } /** * Represent the polynomial as a regular context-less function. */ -public fun > Polynomial.asPolynomialFunctionOver(ring: A): (Polynomial) -> Polynomial = { substitute(ring, it) } +public fun > ListPolynomial.asPolynomialFunctionOver(ring: A): (ListPolynomial) -> ListPolynomial = { substitute(ring, it) } /** * Returns algebraic derivative of received polynomial. */ @UnstableKMathAPI -public fun Polynomial.derivative( +public fun ListPolynomial.derivative( algebra: A, -): Polynomial where A : Ring, A : NumericAlgebra = algebra { - Polynomial( +): ListPolynomial where A : Ring, A : NumericAlgebra = algebra { + ListPolynomial( buildList(max(0, coefficients.size - 1)) { for (deg in 1 .. coefficients.lastIndex) add(number(deg) * coefficients[deg]) while (isNotEmpty() && elementAt(lastIndex) == algebra.zero) removeAt(lastIndex) @@ -177,12 +177,12 @@ public fun Polynomial.derivative( * Returns algebraic derivative of received polynomial. */ @UnstableKMathAPI -public fun Polynomial.nthDerivative( +public fun ListPolynomial.nthDerivative( algebra: A, order: Int, -): Polynomial where A : Ring, A : NumericAlgebra = algebra { +): ListPolynomial where A : Ring, A : NumericAlgebra = algebra { require(order >= 0) { "Order of derivative must be non-negative" } - Polynomial( + 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) }) @@ -195,10 +195,10 @@ public fun Polynomial.nthDerivative( * Returns algebraic antiderivative of received polynomial. */ @UnstableKMathAPI -public fun Polynomial.antiderivative( +public fun ListPolynomial.antiderivative( algebra: A, -): Polynomial where A : Field, A : NumericAlgebra = algebra { - Polynomial( +): ListPolynomial where A : Field, A : NumericAlgebra = algebra { + ListPolynomial( buildList(coefficients.size + 1) { add(zero) coefficients.mapIndexedTo(this) { index, t -> t / number(index + 1) } @@ -211,12 +211,12 @@ public fun Polynomial.antiderivative( * Returns algebraic antiderivative of received polynomial. */ @UnstableKMathAPI -public fun Polynomial.nthAntiderivative( +public fun ListPolynomial.nthAntiderivative( algebra: A, order: Int, -): Polynomial where A : Field, A : NumericAlgebra = algebra { +): ListPolynomial where A : Field, A : NumericAlgebra = algebra { require(order >= 0) { "Order of antiderivative must be non-negative" } - Polynomial( + ListPolynomial( buildList(coefficients.size + order) { repeat(order) { add(zero) } coefficients.mapIndexedTo(this) { index, c -> (1..order).fold(c) { acc, i -> acc / number(index + i) } } @@ -229,7 +229,7 @@ public fun Polynomial.nthAntiderivative( * Compute a definite integral of a given polynomial in a [range] */ @UnstableKMathAPI -public fun > Polynomial.integrate( +public fun > ListPolynomial.integrate( algebra: Field, range: ClosedRange, ): C = algebra { diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/rationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listRationalFunctionUtil.kt similarity index 88% rename from kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/rationalFunctionUtil.kt rename to kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listRationalFunctionUtil.kt index 8d2073834..151c7bb8d 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/rationalFunctionUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listRationalFunctionUtil.kt @@ -14,23 +14,23 @@ import kotlin.math.max /** - * Creates a [RationalFunctionSpace] over a received ring. + * Creates a [ListRationalFunctionSpace] over a received ring. */ -public fun > A.rationalFunction(): RationalFunctionSpace = - RationalFunctionSpace(this) +public fun > A.listRationalFunction(): ListRationalFunctionSpace = + ListRationalFunctionSpace(this) /** - * Creates a [RationalFunctionSpace]'s scope over a received ring. + * Creates a [ListRationalFunctionSpace]'s scope over a received ring. */ -public inline fun , R> A.rationalFunction(block: RationalFunctionSpace.() -> R): R { +public inline fun , R> A.listRationalFunction(block: ListRationalFunctionSpace.() -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return RationalFunctionSpace(this).block() + return ListRationalFunctionSpace(this).block() } /** * Evaluates the value of the given double polynomial for given double argument. */ -public fun RationalFunction.substitute(arg: Double): Double = +public fun ListRationalFunction.substitute(arg: Double): Double = numerator.substitute(arg) / denominator.substitute(arg) /** @@ -38,7 +38,7 @@ public fun RationalFunction.substitute(arg: Double): Double = * * It is an implementation of [Horner's method](https://en.wikipedia.org/wiki/Horner%27s_method). */ -public fun RationalFunction.substitute(ring: Field, arg: C): C = ring { +public fun ListRationalFunction.substitute(ring: Field, arg: C): C = ring { numerator.substitute(ring, arg) / denominator.substitute(ring, arg) } @@ -50,13 +50,13 @@ public fun RationalFunction.substitute(ring: Field, arg: C): C = ring * ``` * is returned. * - * Used in [Polynomial.substitute] and [RationalFunction.substitute] for performance optimisation. + * Used in [ListPolynomial.substitute] and [ListRationalFunction.substitute] for performance optimisation. */ // TODO: Дописать -internal fun Polynomial.substituteRationalFunctionTakeNumerator(ring: Ring, arg: RationalFunction): Polynomial = ring { - if (coefficients.isEmpty()) return Polynomial(emptyList()) +internal fun ListPolynomial.substituteRationalFunctionTakeNumerator(ring: Ring, arg: ListRationalFunction): ListPolynomial = ring { + if (coefficients.isEmpty()) return ListPolynomial(emptyList()) val thisDegree = coefficients.indexOfLast { it != zero } - if (thisDegree == -1) return Polynomial(emptyList()) + if (thisDegree == -1) return ListPolynomial(emptyList()) val thisDegreeLog2 = 31 - thisDegree.countLeadingZeroBits() val numeratorDegree = arg.numerator.coefficients.indexOfLast { it != zero } val denominatorDegree = arg.denominator.coefficients.indexOfLast { it != zero } @@ -189,7 +189,7 @@ internal fun Polynomial.substituteRationalFunctionTakeNumerator(ring: Rin return levelResultCoefs } - return Polynomial( + return ListPolynomial( processLevelEdged( level = thisDegreeLog2, start = 0, diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt index cc725f981..5cd0679ab 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt @@ -17,7 +17,7 @@ public fun > A.numberedRationalFunction(): NumberedRationalFuncti NumberedRationalFunctionSpace(this) /** - * Creates a [RationalFunctionSpace]'s scope over a received ring. + * Creates a [NumberedRationalFunctionSpace]'s scope over a received ring. */ public inline fun , R> A.numberedRationalFunction(block: NumberedRationalFunctionSpace.() -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt index 34d7bcf41..b55f16cf2 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt @@ -7,7 +7,7 @@ package space.kscience.kmath.interpolation import space.kscience.kmath.data.XYColumnarData import space.kscience.kmath.functions.PiecewisePolynomial -import space.kscience.kmath.functions.Polynomial +import space.kscience.kmath.functions.ListPolynomial import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.invoke @@ -32,7 +32,7 @@ public class LinearInterpolator>(override val algebra: Field>( val x02 = x0 * x0 val x03 = x02 * x0 //Shift coefficients to represent absolute polynomial instead of one with an offset - val polynomial = Polynomial( + val polynomial = ListPolynomial( a - b * x0 + c * x02 - d * x03, b - 2 * c * x0 + 3 * d * x02, c - 3 * d * x0, diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt new file mode 100644 index 000000000..0d2c4b5fc --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt @@ -0,0 +1,705 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.test.misc.* +import kotlin.test.* + + +class ListPolynomialTest { + @Test + fun test_Polynomial_Int_plus() { + RationalField.listPolynomial { + 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(), + ListPolynomial(Rational(-2)) + 2, + "test 3" + ) + assertEquals( + ListPolynomial(), + ListPolynomial() + 0, + "test 4" + ) + assertEquals( + ListPolynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), + ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + 1, + "test 5" + ) + assertEquals( + ListPolynomial(Rational(-1)), + ListPolynomial(Rational(-2)) + 1, + "test 6" + ) + assertEquals( + ListPolynomial(Rational(2)), + ListPolynomial() + 2, + "test 7" + ) + } + } + @Test + fun test_Polynomial_Int_minus() { + RationalField.listPolynomial { + 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(), + ListPolynomial(Rational(2)) - 2, + "test 3" + ) + assertEquals( + ListPolynomial(), + ListPolynomial() - 0, + "test 4" + ) + assertEquals( + ListPolynomial(Rational(1), Rational(0), Rational(0), Rational(0)), + ListPolynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - 1, + "test 5" + ) + assertEquals( + ListPolynomial(Rational(1)), + ListPolynomial(Rational(2)) - 1, + "test 6" + ) + assertEquals( + ListPolynomial(Rational(-2)), + ListPolynomial() - 2, + "test 7" + ) + } + } + @Test + fun test_Polynomial_Int_times() { + IntModuloRing(35).listPolynomial { + assertEquals( + ListPolynomial(34, 2, 1, 20, 2), + ListPolynomial(22, 26, 13, 15, 26) * 27, + "test 1" + ) + assertEquals( + ListPolynomial(), + ListPolynomial(7, 0, 49, 21, 14) * 15, + "test 2" + ) + } + } + @Test + fun test_Int_Polynomial_plus() { + RationalField.listPolynomial { + 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(), + 2 + ListPolynomial(Rational(-2)), + "test 3" + ) + assertEquals( + ListPolynomial(), + 0 + ListPolynomial(), + "test 4" + ) + assertEquals( + ListPolynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), + 1 + ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 5" + ) + assertEquals( + ListPolynomial(Rational(-1)), + 1 + ListPolynomial(Rational(-2)), + "test 6" + ) + assertEquals( + ListPolynomial(Rational(2)), + 2 + ListPolynomial(), + "test 7" + ) + } + } + @Test + fun test_Int_Polynomial_minus() { + RationalField.listPolynomial { + 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(), + -2 - ListPolynomial(Rational(-2)), + "test 3" + ) + assertEquals( + ListPolynomial(), + 0 - ListPolynomial(), + "test 4" + ) + assertEquals( + ListPolynomial(Rational(1), Rational(0), Rational(0), Rational(0)), + -1 - ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 5" + ) + assertEquals( + ListPolynomial(Rational(1)), + -1 - ListPolynomial(Rational(-2)), + "test 6" + ) + assertEquals( + ListPolynomial(Rational(-2)), + -2 - ListPolynomial(), + "test 7" + ) + } + } + @Test + fun test_Int_Polynomial_times() { + IntModuloRing(35).listPolynomial { + assertEquals( + ListPolynomial(34, 2, 1, 20, 2), + 27 * ListPolynomial(22, 26, 13, 15, 26), + "test 1" + ) + assertEquals( + ListPolynomial(), + 15 * ListPolynomial(7, 0, 49, 21, 14), + "test 2" + ) + } + } + @Test + fun test_Polynomial_Constant_plus() { + RationalField.listPolynomial { + 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(), + ListPolynomial(Rational(-2)) + Rational(2), + "test 3" + ) + assertEquals( + ListPolynomial(), + 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.listPolynomial { + 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(), + ListPolynomial(Rational(2)) - Rational(2), + "test 3" + ) + assertEquals( + ListPolynomial(), + 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).listPolynomial { + assertEquals( + ListPolynomial(34, 2, 1, 20, 2), + ListPolynomial(22, 26, 13, 15, 26) * number(27), + "test 1" + ) + assertEquals( + ListPolynomial(), + ListPolynomial(7, 0, 49, 21, 14) * number(15), + "test 2" + ) + } + } + @Test + fun test_Constant_Polynomial_plus() { + RationalField.listPolynomial { + 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(2) + ListPolynomial(Rational(-2)), + "test 3" + ) + assertEquals( + ListPolynomial(), + 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.listPolynomial { + 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(-2) - ListPolynomial(Rational(-2)), + "test 3" + ) + assertEquals( + ListPolynomial(), + 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).listPolynomial { + assertEquals( + ListPolynomial(34, 2, 1, 20, 2), + 27 * ListPolynomial(22, 26, 13, 15, 26), + "test 1" + ) + assertEquals( + ListPolynomial(), + 15 * ListPolynomial(7, 0, 49, 21, 14), + "test 2" + ) + } + } + @Test + fun test_Polynomial_unaryMinus() { + RationalField.listPolynomial { + 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.listPolynomial { + // (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)), + 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(), + 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.listPolynomial { + // (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)), + 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(), + 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).listPolynomial { + // (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(), + ListPolynomial(5, -25, 10) * ListPolynomial(21, 14, -7), + "test 2" + ) + } + } + @Test + fun test_Polynomial_isZero() { + RationalField.listPolynomial { + assertTrue("test 1") { ListPolynomial().isZero() } + assertTrue("test 2") { ListPolynomial(Rational(0)).isZero() } + assertTrue("test 3") { ListPolynomial(Rational(0), Rational(0)).isZero() } + assertTrue("test 4") { ListPolynomial(Rational(0), Rational(0), Rational(0)) + .isZero() } + assertFalse("test 5") { ListPolynomial(Rational(3, 5)).isZero() } + assertFalse("test 6") { ListPolynomial(Rational(3, 5), Rational(0)) + .isZero() } + assertFalse("test 7") { ListPolynomial(Rational(0), Rational(3, 5), Rational(0)) + .isZero() } + } + } + @Test + fun test_Polynomial_isOne() { + RationalField.listPolynomial { + assertFalse("test 1") { ListPolynomial().isOne() } + assertFalse("test 2") { ListPolynomial(Rational(0)).isOne() } + assertFalse("test 3") { ListPolynomial(Rational(0), Rational(0)).isOne() } + assertFalse("test 4") { ListPolynomial(Rational(0), Rational(0), Rational(0)) + .isOne() } + assertFalse("test 5") { ListPolynomial(Rational(3, 5)).isOne() } + assertTrue("test 6") { ListPolynomial(Rational(5, 5)).isOne() } + assertFalse("test 7") { ListPolynomial(Rational(3, 5), Rational(0)).isOne() } + assertTrue("test 8") { ListPolynomial(Rational(3, 3), Rational(0)).isOne() } + assertFalse("test 9") { ListPolynomial(Rational(0), Rational(3, 5), Rational(0)) + .isOne() } + assertFalse("test 10") { ListPolynomial(Rational(0), Rational(5, 5), Rational(0)) + .isOne() } + assertFalse("test 11") { ListPolynomial(Rational(1), Rational(3, 5), Rational(0)) + .isOne() } + assertFalse("test 12") { ListPolynomial(Rational(1), Rational(5, 5), Rational(0)) + .isOne() } + } + } + @Test + fun test_Polynomial_isMinusOne() { + RationalField.listPolynomial { + assertFalse("test 1") { ListPolynomial().isMinusOne() } + assertFalse("test 2") { ListPolynomial(Rational(0)).isMinusOne() } + assertFalse("test 3") { ListPolynomial(Rational(0), Rational(0)).isMinusOne() } + assertFalse("test 4") { ListPolynomial(Rational(0), Rational(0), Rational(0)) + .isMinusOne() } + assertFalse("test 5") { ListPolynomial(Rational(3, 5)).isMinusOne() } + assertTrue("test 6") { ListPolynomial(Rational(-5, 5)).isMinusOne() } + assertFalse("test 7") { ListPolynomial(Rational(3, 5), Rational(0)).isMinusOne() } + assertTrue("test 8") { ListPolynomial(Rational(-3, 3), Rational(0)).isMinusOne() } + assertFalse("test 9") { ListPolynomial(Rational(0), Rational(3, 5), Rational(0)) + .isMinusOne() } + assertFalse("test 10") { ListPolynomial(Rational(0), Rational(5, -5), Rational(0)) + .isMinusOne() } + assertFalse("test 11") { ListPolynomial(Rational(-1), Rational(3, 5), Rational(0)) + .isMinusOne() } + assertFalse("test 12") { ListPolynomial(Rational(-1), Rational(5, -5), Rational(0)) + .isMinusOne() } + } + } + @Test + fun test_Polynomial_Polynomial_equalsTo() { + RationalField.listPolynomial { + assertTrue("test 1") { + ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) equalsTo + ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + } + assertTrue("test 2") { + ListPolynomial(Rational(5, 9), Rational(0), Rational(-8, 7)) equalsTo + ListPolynomial(Rational(5, 9), Rational(0), Rational(-8, 7)) + } + assertTrue("test 3") { + ListPolynomial(Rational(0), Rational(0), Rational(-8, 7), Rational(0), Rational(0)) equalsTo + ListPolynomial(Rational(0), Rational(0), Rational(-8, 7)) + } + assertFalse("test 4") { + ListPolynomial(Rational(5, 9), Rational(5, 7), Rational(-8, 7)) equalsTo + ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + } + assertFalse("test 5") { + ListPolynomial(Rational(8, 3), Rational(0), Rational(-8, 7)) equalsTo + ListPolynomial(Rational(5, 9), Rational(0), Rational(-8, 7)) + } + assertFalse("test 6") { + ListPolynomial(Rational(0), Rational(0), Rational(-8, 7), Rational(0), Rational(0)) equalsTo + ListPolynomial(Rational(0), Rational(0), Rational(8, 7)) + } + } + } + @Test + fun test_Polynomial_degree() { + RationalField.listPolynomial { + assertEquals( + 2, + ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)).degree, + "test 1" + ) + assertEquals( + -1, + ListPolynomial().degree, + "test 2" + ) + assertEquals( + -1, + ListPolynomial(Rational(0)).degree, + "test 3" + ) + assertEquals( + -1, + ListPolynomial(Rational(0), Rational(0)).degree, + "test 4" + ) + assertEquals( + -1, + ListPolynomial(Rational(0), Rational(0), Rational(0)).degree, + "test 5" + ) + assertEquals( + 0, + ListPolynomial(Rational(5, 9)).degree, + "test 6" + ) + assertEquals( + 0, + ListPolynomial(Rational(5, 9), Rational(0)).degree, + "test 7" + ) + assertEquals( + 0, + ListPolynomial(Rational(5, 9), Rational(0), Rational(0)).degree, + "test 8" + ) + assertEquals( + 2, + ListPolynomial(Rational(0), Rational(0), Rational(-8, 7)).degree, + "test 9" + ) + assertEquals( + 2, + ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7), Rational(0), Rational(0)).degree, + "test 10" + ) + assertEquals( + 2, + ListPolynomial(Rational(0), Rational(0), Rational(-8, 7), Rational(0), Rational(0)).degree, + "test 11" + ) + } + } + @Test + fun test_Polynomial_asConstantOrNull() { + RationalField.listPolynomial { + assertEquals( + Rational(0), + ListPolynomial().asConstantOrNull(), + "test 1" + ) + assertEquals( + Rational(0), + ListPolynomial(Rational(0)).asConstantOrNull(), + "test 2" + ) + assertEquals( + Rational(0), + ListPolynomial(Rational(0), Rational(0)).asConstantOrNull(), + "test 3" + ) + assertEquals( + Rational(0), + ListPolynomial(Rational(0), Rational(0), Rational(0)).asConstantOrNull(), + "test 4" + ) + assertEquals( + Rational(-7, 9), + ListPolynomial(Rational(-7, 9)).asConstantOrNull(), + "test 5" + ) + assertEquals( + Rational(-7, 9), + ListPolynomial(Rational(-7, 9), Rational(0)).asConstantOrNull(), + "test 6" + ) + assertEquals( + Rational(-7, 9), + ListPolynomial(Rational(-7, 9), Rational(0), Rational(0)).asConstantOrNull(), + "test 7" + ) + assertEquals( + null, + ListPolynomial(Rational(0), Rational(-7, 9)).asConstantOrNull(), + "test 8" + ) + assertEquals( + null, + ListPolynomial(Rational(0), Rational(-7, 9), Rational(0)).asConstantOrNull(), + "test 9" + ) + assertEquals( + null, + ListPolynomial(Rational(0), Rational(0), Rational(-7, 9)).asConstantOrNull(), + "test 10" + ) + assertEquals( + null, + ListPolynomial(Rational(4, 15), Rational(0), Rational(-7, 9)).asConstantOrNull(), + "test 11" + ) + assertEquals( + null, + ListPolynomial(Rational(4, 15), Rational(0), Rational(-7, 9), Rational(0)) + .asConstantOrNull(), + "test 12" + ) + } + } +} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt new file mode 100644 index 000000000..bec46c034 --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt @@ -0,0 +1,229 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.test.misc.Rational +import space.kscience.kmath.test.misc.RationalField +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith + + +class ListPolynomialUtilTest { + @Test + fun test_substitute_Double() { + val polynomial = ListPolynomial(1.0, -2.0, 1.0) + assertEquals(0.0, polynomial.substitute(1.0), 0.001) + } + @Test + fun test_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_substitute_Polynomial() { + assertEquals( + ListPolynomial(), + 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)), + 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)), + ListPolynomial(Rational(0), Rational(9, 4), Rational(1, 3), Rational(0)) + .substitute(RationalField, ListPolynomial(Rational(6, 9), Rational(0))), + "test 6" + ) + } + @Test + fun test_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)), + ListPolynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).derivative(RationalField), + "test 4" + ) + } + @Test + fun test_nthDerivative() { + assertEquals( + ListPolynomial(Rational(-2), Rational(2)), + ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, 1), + "test 1" + ) + assertFailsWith("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)), + ListPolynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).nthDerivative(RationalField, 2), + "test 9" + ) + } + @Test + fun test_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)), + ListPolynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).antiderivative(RationalField), + "test 4" + ) + } + @Test + fun test_nthAntiderivative() { + assertEquals( + ListPolynomial(Rational(0), Rational(1), Rational(-1), Rational(1, 3)), + ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, 1), + "test 1" + ) + assertFailsWith("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)), + 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-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt deleted file mode 100644 index 141bdd436..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt +++ /dev/null @@ -1,691 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.test.misc.* -import kotlin.test.* - - -class PolynomialTest { - @Test - fun test_Polynomial_Int_plus() { - RationalField.polynomial { - assertEquals( - Polynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)), - Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + -3, - "test 1" - ) - assertEquals( - Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)), - Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + 2, - "test 2" - ) - assertEquals( - Polynomial(), - Polynomial(Rational(-2)) + 2, - "test 3" - ) - assertEquals( - Polynomial(), - Polynomial() + 0, - "test 4" - ) - assertEquals( - Polynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), - Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + 1, - "test 5" - ) - assertEquals( - Polynomial(Rational(-1)), - Polynomial(Rational(-2)) + 1, - "test 6" - ) - assertEquals( - Polynomial(Rational(2)), - Polynomial() + 2, - "test 7" - ) - } - } - @Test - fun test_Polynomial_Int_minus() { - RationalField.polynomial { - assertEquals( - Polynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), - Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - -3, - "test 1" - ) - assertEquals( - Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)), - Polynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - 2, - "test 2" - ) - assertEquals( - Polynomial(), - Polynomial(Rational(2)) - 2, - "test 3" - ) - assertEquals( - Polynomial(), - Polynomial() - 0, - "test 4" - ) - assertEquals( - Polynomial(Rational(1), Rational(0), Rational(0), Rational(0)), - Polynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - 1, - "test 5" - ) - assertEquals( - Polynomial(Rational(1)), - Polynomial(Rational(2)) - 1, - "test 6" - ) - assertEquals( - Polynomial(Rational(-2)), - Polynomial() - 2, - "test 7" - ) - } - } - @Test - fun test_Polynomial_Int_times() { - IntModuloRing(35).polynomial { - assertEquals( - Polynomial(34, 2, 1, 20, 2), - Polynomial(22, 26, 13, 15, 26) * 27, - "test 1" - ) - assertEquals( - Polynomial(), - Polynomial(7, 0, 49, 21, 14) * 15, - "test 2" - ) - } - } - @Test - fun test_Int_Polynomial_plus() { - RationalField.polynomial { - assertEquals( - Polynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)), - -3 + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)), - "test 1" - ) - assertEquals( - Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)), - 2 + Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), - "test 2" - ) - assertEquals( - Polynomial(), - 2 + Polynomial(Rational(-2)), - "test 3" - ) - assertEquals( - Polynomial(), - 0 + Polynomial(), - "test 4" - ) - assertEquals( - Polynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), - 1 + Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), - "test 5" - ) - assertEquals( - Polynomial(Rational(-1)), - 1 + Polynomial(Rational(-2)), - "test 6" - ) - assertEquals( - Polynomial(Rational(2)), - 2 + Polynomial(), - "test 7" - ) - } - } - @Test - fun test_Int_Polynomial_minus() { - RationalField.polynomial { - assertEquals( - Polynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), - 3 - Polynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7)), - "test 1" - ) - assertEquals( - Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)), - -2 - Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), - "test 2" - ) - assertEquals( - Polynomial(), - -2 - Polynomial(Rational(-2)), - "test 3" - ) - assertEquals( - Polynomial(), - 0 - Polynomial(), - "test 4" - ) - assertEquals( - Polynomial(Rational(1), Rational(0), Rational(0), Rational(0)), - -1 - Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), - "test 5" - ) - assertEquals( - Polynomial(Rational(1)), - -1 - Polynomial(Rational(-2)), - "test 6" - ) - assertEquals( - Polynomial(Rational(-2)), - -2 - Polynomial(), - "test 7" - ) - } - } - @Test - fun test_Int_Polynomial_times() { - IntModuloRing(35).polynomial { - assertEquals( - Polynomial(34, 2, 1, 20, 2), - 27 * Polynomial(22, 26, 13, 15, 26), - "test 1" - ) - assertEquals( - Polynomial(), - 15 * Polynomial(7, 0, 49, 21, 14), - "test 2" - ) - } - } - @Test - fun test_Polynomial_Constant_plus() { - RationalField.polynomial { - assertEquals( - Polynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)), - Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + Rational(-3), - "test 1" - ) - assertEquals( - Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)), - Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + Rational(2), - "test 2" - ) - assertEquals( - Polynomial(), - Polynomial(Rational(-2)) + Rational(2), - "test 3" - ) - assertEquals( - Polynomial(), - Polynomial() + Rational(0), - "test 4" - ) - assertEquals( - Polynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), - Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + Rational(1), - "test 5" - ) - assertEquals( - Polynomial(Rational(-1)), - Polynomial(Rational(-2)) + Rational(1), - "test 6" - ) - assertEquals( - Polynomial(Rational(2)), - Polynomial() + Rational(2), - "test 7" - ) - } - } - @Test - fun test_Polynomial_Constant_minus() { - RationalField.polynomial { - assertEquals( - Polynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), - Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - Rational(-3), - "test 1" - ) - assertEquals( - Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)), - Polynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - Rational(2), - "test 2" - ) - assertEquals( - Polynomial(), - Polynomial(Rational(2)) - Rational(2), - "test 3" - ) - assertEquals( - Polynomial(), - Polynomial() - Rational(0), - "test 4" - ) - assertEquals( - Polynomial(Rational(1), Rational(0), Rational(0), Rational(0)), - Polynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - Rational(1), - "test 5" - ) - assertEquals( - Polynomial(Rational(1)), - Polynomial(Rational(2)) - Rational(1), - "test 6" - ) - assertEquals( - Polynomial(Rational(-2)), - Polynomial() - Rational(2), - "test 7" - ) - } - } - @Test - fun test_Polynomial_Constant_times() { - IntModuloRing(35).polynomial { - assertEquals( - Polynomial(34, 2, 1, 20, 2), - Polynomial(22, 26, 13, 15, 26) * number(27), - "test 1" - ) - assertEquals( - Polynomial(), - Polynomial(7, 0, 49, 21, 14) * number(15), - "test 2" - ) - } - } - @Test - fun test_Constant_Polynomial_plus() { - RationalField.polynomial { - assertEquals( - Polynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)), - Rational(-3) + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)), - "test 1" - ) - assertEquals( - Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)), - Rational(2) + Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), - "test 2" - ) - assertEquals( - Polynomial(), - Rational(2) + Polynomial(Rational(-2)), - "test 3" - ) - assertEquals( - Polynomial(), - Rational(0) + Polynomial(), - "test 4" - ) - assertEquals( - Polynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), - Rational(1) + Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), - "test 5" - ) - assertEquals( - Polynomial(Rational(-1)), - Rational(1) + Polynomial(Rational(-2)), - "test 6" - ) - assertEquals( - Polynomial(Rational(2)), - Rational(2) + Polynomial(), - "test 7" - ) - } - } - @Test - fun test_Constant_Polynomial_minus() { - RationalField.polynomial { - assertEquals( - Polynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), - Rational(3) - Polynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7)), - "test 1" - ) - assertEquals( - Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)), - Rational(-2) - Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), - "test 2" - ) - assertEquals( - Polynomial(), - Rational(-2) - Polynomial(Rational(-2)), - "test 3" - ) - assertEquals( - Polynomial(), - Rational(0) - Polynomial(), - "test 4" - ) - assertEquals( - Polynomial(Rational(1), Rational(0), Rational(0), Rational(0)), - Rational(-1) - Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), - "test 5" - ) - assertEquals( - Polynomial(Rational(1)), - Rational(-1) - Polynomial(Rational(-2)), - "test 6" - ) - assertEquals( - Polynomial(Rational(-2)), - Rational(-2) - Polynomial(), - "test 7" - ) - } - } - @Test - fun test_Constant_Polynomial_times() { - IntModuloRing(35).polynomial { - assertEquals( - Polynomial(34, 2, 1, 20, 2), - 27 * Polynomial(22, 26, 13, 15, 26), - "test 1" - ) - assertEquals( - Polynomial(), - 15 * Polynomial(7, 0, 49, 21, 14), - "test 2" - ) - } - } - @Test - fun test_Polynomial_unaryMinus() { - RationalField.polynomial { - assertEquals( - Polynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7)), - -Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)), - "test 1" - ) - assertEquals( - Polynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7), Rational(0), Rational(0)), - -Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7), Rational(0), Rational(0)), - "test 2" - ) - } - } - @Test - fun test_Polynomial_Polynomial_plus() { - RationalField.polynomial { - // (5/9 - 8/9 x - 8/7 x^2) + (-5/7 + 5/1 x + 5/8 x^2) ?= -10/63 + 37/9 x - 29/56 x^2 - assertEquals( - Polynomial(Rational(-10, 63), Rational(37, 9), Rational(-29, 56)), - Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + - Polynomial(Rational(-5, 7), Rational(5, 1), Rational(5, 8)), - "test 1" - ) - // (-2/9 - 8/3 x) + (0 + 9/4 x + 2/4 x^2) ?= -2/9 - 5/12 x + 2/4 x^2 - assertEquals( - Polynomial(Rational(-2, 9), Rational(-5, 12), Rational(2, 4)), - Polynomial(Rational(-2, 9), Rational(-8, 3)) + - Polynomial(Rational(0), Rational(9, 4), Rational(2, 4)), - "test 2" - ) - // (-4/7 - 2/6 x + 0 x^2 + 0 x^3) + (-6/3 - 7/2 x + 2/3 x^2) ?= -18/7 - 23/6 x + 2/3 x^2 - assertEquals( - Polynomial(Rational(-18, 7), Rational(-23, 6), Rational(2, 3)), - Polynomial(Rational(-4, 7), Rational(-2, 6), Rational(0), Rational(0)) + - Polynomial(Rational(-6, 3), Rational(-7, 2), Rational(2, 3)), - "test 3" - ) - // (-2/4 - 6/9 x - 4/9 x^2) + (2/4 + 6/9 x + 4/9 x^2) ?= 0 - assertEquals( - Polynomial(), - Polynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)) + - Polynomial(Rational(2, 4), Rational(6, 9), Rational(4, 9)), - "test 4" - ) - } - } - @Test - fun test_Polynomial_Polynomial_minus() { - RationalField.polynomial { - // (5/9 - 8/9 x - 8/7 x^2) - (-5/7 + 5/1 x + 5/8 x^2) ?= 80/63 - 53/9 x - 99/56 x^2 - assertEquals( - Polynomial(Rational(80, 63), Rational(-53, 9), Rational(-99, 56)), - Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - - Polynomial(Rational(-5, 7), Rational(5, 1), Rational(5, 8)), - "test 1" - ) - // (-2/9 - 8/3 x) - (0 + 9/4 x + 2/4 x^2) ?= -2/9 - 59/12 x - 2/4 x^2 - assertEquals( - Polynomial(Rational(-2, 9), Rational(-59, 12), Rational(-2, 4)), - Polynomial(Rational(-2, 9), Rational(-8, 3)) - - Polynomial(Rational(0), Rational(9, 4), Rational(2, 4)), - "test 2" - ) - // (-4/7 - 2/6 x + 0 x^2 + 0 x^3) - (-6/3 - 7/2 x + 2/3 x^2) ?= 10/7 + 19/6 x - 2/3 x^2 - assertEquals( - Polynomial(Rational(10, 7), Rational(19, 6), Rational(-2, 3)), - Polynomial(Rational(-4, 7), Rational(-2, 6), Rational(0), Rational(0)) - - Polynomial(Rational(-6, 3), Rational(-7, 2), Rational(2, 3)), - "test 3" - ) - // (-2/4 - 6/9 x - 4/9 x^2) - (-2/4 - 6/9 x - 4/9 x^2) ?= 0 - assertEquals( - Polynomial(), - Polynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)) - - Polynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)), - "test 4" - ) - } - } - @Test - fun test_Polynomial_Polynomial_times() { - IntModuloRing(35).polynomial { - // (1 + x + x^2) * (1 - x + x^2) ?= 1 + x^2 + x^4 - assertEquals( - Polynomial(1, 0, 1, 0, 1), - Polynomial(1, -1, 1) * Polynomial(1, 1, 1), - "test 1" - ) - // Spoiler: 5 * 7 = 0 - assertEquals( - Polynomial(), - Polynomial(5, -25, 10) * Polynomial(21, 14, -7), - "test 2" - ) - } - } - @Test - fun test_Polynomial_isZero() { - RationalField.polynomial { - assertTrue("test 1") { Polynomial().isZero() } - assertTrue("test 2") { Polynomial(Rational(0)).isZero() } - assertTrue("test 3") { Polynomial(Rational(0), Rational(0)).isZero() } - assertTrue("test 4") { Polynomial(Rational(0), Rational(0), Rational(0)).isZero() } - assertFalse("test 5") { Polynomial(Rational(3, 5)).isZero() } - assertFalse("test 6") { Polynomial(Rational(3, 5), Rational(0)).isZero() } - assertFalse("test 7") { Polynomial(Rational(0), Rational(3, 5), Rational(0)).isZero() } - } - } - @Test - fun test_Polynomial_isOne() { - RationalField.polynomial { - assertFalse("test 1") { Polynomial().isOne() } - assertFalse("test 2") { Polynomial(Rational(0)).isOne() } - assertFalse("test 3") { Polynomial(Rational(0), Rational(0)).isOne() } - assertFalse("test 4") { Polynomial(Rational(0), Rational(0), Rational(0)).isOne() } - assertFalse("test 5") { Polynomial(Rational(3, 5)).isOne() } - assertTrue("test 6") { Polynomial(Rational(5, 5)).isOne() } - assertFalse("test 7") { Polynomial(Rational(3, 5), Rational(0)).isOne() } - assertTrue("test 8") { Polynomial(Rational(3, 3), Rational(0)).isOne() } - assertFalse("test 9") { Polynomial(Rational(0), Rational(3, 5), Rational(0)).isOne() } - assertFalse("test 10") { Polynomial(Rational(0), Rational(5, 5), Rational(0)).isOne() } - assertFalse("test 11") { Polynomial(Rational(1), Rational(3, 5), Rational(0)).isOne() } - assertFalse("test 12") { Polynomial(Rational(1), Rational(5, 5), Rational(0)).isOne() } - } - } - @Test - fun test_Polynomial_isMinusOne() { - RationalField.polynomial { - assertFalse("test 1") { Polynomial().isMinusOne() } - assertFalse("test 2") { Polynomial(Rational(0)).isMinusOne() } - assertFalse("test 3") { Polynomial(Rational(0), Rational(0)).isMinusOne() } - assertFalse("test 4") { Polynomial(Rational(0), Rational(0), Rational(0)).isMinusOne() } - assertFalse("test 5") { Polynomial(Rational(3, 5)).isMinusOne() } - assertTrue("test 6") { Polynomial(Rational(-5, 5)).isMinusOne() } - assertFalse("test 7") { Polynomial(Rational(3, 5), Rational(0)).isMinusOne() } - assertTrue("test 8") { Polynomial(Rational(-3, 3), Rational(0)).isMinusOne() } - assertFalse("test 9") { Polynomial(Rational(0), Rational(3, 5), Rational(0)).isMinusOne() } - assertFalse("test 10") { Polynomial(Rational(0), Rational(5, -5), Rational(0)).isMinusOne() } - assertFalse("test 11") { Polynomial(Rational(-1), Rational(3, 5), Rational(0)).isMinusOne() } - assertFalse("test 12") { Polynomial(Rational(-1), Rational(5, -5), Rational(0)).isMinusOne() } - } - } - @Test - fun test_Polynomial_equalsTo() { - RationalField.polynomial { - assertTrue("test 1") { - Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) equalsTo - Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - } - assertTrue("test 2") { - Polynomial(Rational(5, 9), Rational(0), Rational(-8, 7)) equalsTo - Polynomial(Rational(5, 9), Rational(0), Rational(-8, 7)) - } - assertTrue("test 3") { - Polynomial(Rational(0), Rational(0), Rational(-8, 7), Rational(0), Rational(0)) equalsTo - Polynomial(Rational(0), Rational(0), Rational(-8, 7)) - } - assertFalse("test 4") { - Polynomial(Rational(5, 9), Rational(5, 7), Rational(-8, 7)) equalsTo - Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - } - assertFalse("test 5") { - Polynomial(Rational(8, 3), Rational(0), Rational(-8, 7)) equalsTo - Polynomial(Rational(5, 9), Rational(0), Rational(-8, 7)) - } - assertFalse("test 6") { - Polynomial(Rational(0), Rational(0), Rational(-8, 7), Rational(0), Rational(0)) equalsTo - Polynomial(Rational(0), Rational(0), Rational(8, 7)) - } - } - } - @Test - fun test_Polynomial_degree() { - RationalField.polynomial { - assertEquals( - 2, - Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)).degree, - "test 1" - ) - assertEquals( - -1, - Polynomial().degree, - "test 2" - ) - assertEquals( - -1, - Polynomial(Rational(0)).degree, - "test 3" - ) - assertEquals( - -1, - Polynomial(Rational(0), Rational(0)).degree, - "test 4" - ) - assertEquals( - -1, - Polynomial(Rational(0), Rational(0), Rational(0)).degree, - "test 5" - ) - assertEquals( - 0, - Polynomial(Rational(5, 9)).degree, - "test 6" - ) - assertEquals( - 0, - Polynomial(Rational(5, 9), Rational(0)).degree, - "test 7" - ) - assertEquals( - 0, - Polynomial(Rational(5, 9), Rational(0), Rational(0)).degree, - "test 8" - ) - assertEquals( - 2, - Polynomial(Rational(0), Rational(0), Rational(-8, 7)).degree, - "test 9" - ) - assertEquals( - 2, - Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7), Rational(0), Rational(0)).degree, - "test 10" - ) - assertEquals( - 2, - Polynomial(Rational(0), Rational(0), Rational(-8, 7), Rational(0), Rational(0)).degree, - "test 11" - ) - } - } - @Test - fun test_Polynomial_asConstantOrNull() { - RationalField.polynomial { - assertEquals( - Rational(0), - Polynomial().asConstantOrNull(), - "test 1" - ) - assertEquals( - Rational(0), - Polynomial(Rational(0)).asConstantOrNull(), - "test 2" - ) - assertEquals( - Rational(0), - Polynomial(Rational(0), Rational(0)).asConstantOrNull(), - "test 3" - ) - assertEquals( - Rational(0), - Polynomial(Rational(0), Rational(0), Rational(0)).asConstantOrNull(), - "test 4" - ) - assertEquals( - Rational(-7, 9), - Polynomial(Rational(-7, 9)).asConstantOrNull(), - "test 5" - ) - assertEquals( - Rational(-7, 9), - Polynomial(Rational(-7, 9), Rational(0)).asConstantOrNull(), - "test 6" - ) - assertEquals( - Rational(-7, 9), - Polynomial(Rational(-7, 9), Rational(0), Rational(0)).asConstantOrNull(), - "test 7" - ) - assertEquals( - null, - Polynomial(Rational(0), Rational(-7, 9)).asConstantOrNull(), - "test 8" - ) - assertEquals( - null, - Polynomial(Rational(0), Rational(-7, 9), Rational(0)).asConstantOrNull(), - "test 9" - ) - assertEquals( - null, - Polynomial(Rational(0), Rational(0), Rational(-7, 9)).asConstantOrNull(), - "test 10" - ) - assertEquals( - null, - Polynomial(Rational(4, 15), Rational(0), Rational(-7, 9)).asConstantOrNull(), - "test 11" - ) - assertEquals( - null, - Polynomial(Rational(4, 15), Rational(0), Rational(-7, 9), Rational(0)).asConstantOrNull(), - "test 12" - ) - } - } -} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt deleted file mode 100644 index 21c5436d3..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.test.misc.Rational -import space.kscience.kmath.test.misc.RationalField -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith - - -class PolynomialUtilTest { - @Test - fun test_substitute_Double() { - val polynomial = Polynomial(1.0, -2.0, 1.0) - assertEquals(0.0, polynomial.substitute(1.0), 0.001) - } - @Test - fun test_substitute_Constant() { - assertEquals( - Rational(0), - Polynomial(Rational(1), Rational(-2), Rational(1)).substitute(RationalField, Rational(1)), - "test 1" - ) - assertEquals( - Rational(25057, 21000), - Polynomial(Rational(5,8), Rational(8, 3), Rational(4, 7), Rational(3, 2)) - .substitute(RationalField, Rational(1, 5)), - "test 2" - ) - assertEquals( - Rational(2983, 5250), - Polynomial(Rational(0), Rational(8, 3), Rational(4, 7), Rational(3, 2)) - .substitute(RationalField, Rational(1, 5)), - "test 3" - ) - assertEquals( - Rational(4961, 4200), - Polynomial(Rational(5,8), Rational(8, 3), Rational(4, 7), Rational(0)) - .substitute(RationalField, Rational(1, 5)), - "test 4" - ) - assertEquals( - Rational(3511, 3000), - Polynomial(Rational(5,8), Rational(8, 3), Rational(0), Rational(3, 2)) - .substitute(RationalField, Rational(1, 5)), - "test 5" - ) - } - @Test - fun test_substitute_Polynomial() { - assertEquals( - Polynomial(), - Polynomial(Rational(1), Rational(-2), Rational(1)).substitute(RationalField, Polynomial(Rational(1))), - "test 1" - ) - assertEquals( - Polynomial(Rational(709, 378), Rational(155, 252), Rational(19, 525), Rational(2, 875)), - Polynomial(Rational(1, 7), Rational(9, 4), Rational(1, 3), Rational(2, 7)) - .substitute(RationalField, Polynomial(Rational(6, 9), Rational(1, 5))), - "test 2" - ) - assertEquals( - Polynomial(Rational(655, 378), Rational(155, 252), Rational(19, 525), Rational(2, 875)), - Polynomial(Rational(0), Rational(9, 4), Rational(1, 3), Rational(2, 7)) - .substitute(RationalField, Polynomial(Rational(6, 9), Rational(1, 5))), - "test 3" - ) - assertEquals( - Polynomial(Rational(677, 378), Rational(97, 180), Rational(1, 75)), - Polynomial(Rational(1, 7), Rational(9, 4), Rational(1, 3), Rational(0)) - .substitute(RationalField, Polynomial(Rational(6, 9), Rational(1, 5))), - "test 4" - ) - assertEquals( - Polynomial(Rational(653, 378), Rational(221, 420), Rational(4, 175), Rational(2, 875)), - Polynomial(Rational(1, 7), Rational(9, 4), Rational(0), Rational(2, 7)) - .substitute(RationalField, Polynomial(Rational(6, 9), Rational(1, 5))), - "test 5" - ) - assertEquals( - Polynomial(Rational(89, 54)), - Polynomial(Rational(0), Rational(9, 4), Rational(1, 3), Rational(0)) - .substitute(RationalField, Polynomial(Rational(6, 9), Rational(0))), - "test 6" - ) - } - @Test - fun test_derivative() { - assertEquals( - Polynomial(Rational(-2), Rational(2)), - Polynomial(Rational(1), Rational(-2), Rational(1)).derivative(RationalField), - "test 1" - ) - assertEquals( - Polynomial(Rational(-8, 3), Rational(8, 9), Rational(15, 7), Rational(-20, 9)), - Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).derivative(RationalField), - "test 2" - ) - assertEquals( - Polynomial(Rational(0), Rational(8, 9), Rational(15, 7), Rational(-20, 9)), - Polynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).derivative(RationalField), - "test 3" - ) - assertEquals( - Polynomial(Rational(-8, 3), Rational(8, 9), Rational(15, 7)), - Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).derivative(RationalField), - "test 4" - ) - } - @Test - fun test_nthDerivative() { - assertEquals( - Polynomial(Rational(-2), Rational(2)), - Polynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, 1), - "test 1" - ) - assertFailsWith("test2") { - Polynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, -1) - } - assertEquals( - Polynomial(Rational(1), Rational(-2), Rational(1)), - Polynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, 0), - "test 3" - ) - assertEquals( - Polynomial(Rational(2)), - Polynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, 2), - "test 4" - ) - assertEquals( - Polynomial(), - Polynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, 3), - "test 5" - ) - assertEquals( - Polynomial(), - Polynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, 4), - "test 6" - ) - assertEquals( - Polynomial(Rational(8, 9), Rational(30, 7), Rational(-20, 3)), - Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).nthDerivative(RationalField, 2), - "test 7" - ) - assertEquals( - Polynomial(Rational(8, 9), Rational(30, 7), Rational(-20, 3)), - Polynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).nthDerivative(RationalField, 2), - "test 8" - ) - assertEquals( - Polynomial(Rational(8, 9), Rational(30, 7)), - Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).nthDerivative(RationalField, 2), - "test 9" - ) - } - @Test - fun test_antiderivative() { - assertEquals( - Polynomial(Rational(0), Rational(1), Rational(-1), Rational(1, 3)), - Polynomial(Rational(1), Rational(-2), Rational(1)).antiderivative(RationalField), - "test 1" - ) - assertEquals( - Polynomial(Rational(0), Rational(1, 5), Rational(-4, 3), Rational(4, 27), Rational(5, 28), Rational(-1, 9)), - Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).antiderivative(RationalField), - "test 2" - ) - assertEquals( - Polynomial(Rational(0), Rational(0), Rational(0), Rational(4, 27), Rational(5, 28), Rational(-1, 9)), - Polynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).antiderivative(RationalField), - "test 3" - ) - assertEquals( - Polynomial(Rational(0), Rational(1, 5), Rational(-4, 3), Rational(4, 27), Rational(5, 28)), - Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).antiderivative(RationalField), - "test 4" - ) - } - @Test - fun test_nthAntiderivative() { - assertEquals( - Polynomial(Rational(0), Rational(1), Rational(-1), Rational(1, 3)), - Polynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, 1), - "test 1" - ) - assertFailsWith("test2") { - Polynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, -1) - } - assertEquals( - Polynomial(Rational(1), Rational(-2), Rational(1)), - Polynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, 0), - "test 3" - ) - assertEquals( - Polynomial(Rational(0), Rational(0), Rational(1, 2), Rational(-1, 3), Rational(1, 12)), - Polynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, 2), - "test 4" - ) - assertEquals( - Polynomial(Rational(0), Rational(0), Rational(0), Rational(1, 6), Rational(-1, 12), Rational(1, 60)), - Polynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, 3), - "test 5" - ) - assertEquals( - Polynomial(Rational(0), Rational(0), Rational(0), Rational(0), Rational(1, 24), Rational(-1, 60), Rational(1, 360)), - Polynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, 4), - "test 6" - ) - assertEquals( - Polynomial(Rational(0), Rational(0), Rational(1, 10), Rational(-4, 9), Rational(1, 27), Rational(1, 28), Rational(-1, 54)), - Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).nthAntiderivative(RationalField, 2), - "test 7" - ) - assertEquals( - Polynomial(Rational(0), Rational(0), Rational(0), Rational(0), Rational(1, 27), Rational(1, 28), Rational(-1, 54)), - Polynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).nthAntiderivative(RationalField, 2), - "test 8" - ) - assertEquals( - Polynomial(Rational(0), Rational(0), Rational(1, 10), Rational(-4, 9), Rational(1, 27), Rational(1, 28)), - Polynomial(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-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt index afeba0be4..aae0ad017 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.integration -import space.kscience.kmath.functions.Polynomial +import space.kscience.kmath.functions.ListPolynomial import space.kscience.kmath.functions.integrate import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField @@ -19,7 +19,7 @@ class SplineIntegralTest { @Test fun integratePolynomial(){ - val polynomial = Polynomial(1.0, 2.0, 3.0) + val polynomial = ListPolynomial(1.0, 2.0, 3.0) val integral = polynomial.integrate(DoubleField,1.0..2.0) assertEquals(11.0, integral, 0.001) } diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt index a8a8a09bc..535a42846 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt @@ -5,8 +5,8 @@ package space.kscience.kmath.test.misc -import space.kscience.kmath.functions.Polynomial -import space.kscience.kmath.functions.PolynomialSpace +import space.kscience.kmath.functions.ListPolynomial +import space.kscience.kmath.functions.ListPolynomialSpace import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Ring @@ -134,9 +134,9 @@ class IntModuloRing : Ring { inline fun IntModulo.div(arg: IntModulo): IntModulo = this / arg } -fun PolynomialSpace.number(arg: Int) = IntModulo(arg, ring.modulus, toCheckInput = false) +fun ListPolynomialSpace.number(arg: Int) = IntModulo(arg, ring.modulus, toCheckInput = false) -fun PolynomialSpace.Polynomial(vararg coefs: Int): Polynomial = - Polynomial(coefs.map { IntModulo(it, ring.modulus) }) -fun IntModuloRing.Polynomial(vararg coefs: Int): Polynomial = - Polynomial(coefs.map { IntModulo(it, modulus) }) \ No newline at end of file +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) }) \ No newline at end of file -- 2.34.1 From 98b9a708937213eda5160805638e9d851869c7cc Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 22 Mar 2022 02:37:26 +0300 Subject: [PATCH 054/275] Enhanced tests of Double substitution. --- .../kmath/functions/ListPolynomialUtilTest.kt | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt index bec46c034..50ae18260 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt @@ -15,8 +15,36 @@ import kotlin.test.assertFailsWith class ListPolynomialUtilTest { @Test fun test_substitute_Double() { - val polynomial = ListPolynomial(1.0, -2.0, 1.0) - assertEquals(0.0, polynomial.substitute(1.0), 0.001) + 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_substitute_Constant() { -- 2.34.1 From 09868f090b7507ae9ecb8ad17cc5dad75899c5b3 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 22 Mar 2022 02:39:43 +0300 Subject: [PATCH 055/275] Enhanced tests of Double substitution. --- .../kmath/functions/LabeledPolynomial.kt | 10 +++++- .../kmath/functions/ListPolynomial.kt | 12 ++++++- .../kmath/functions/NumberedPolynomial.kt | 10 +++++- .../kscience/kmath/functions/Polynomial.kt | 10 ++++++ .../kmath/functions/RationalFunction.kt | 31 +++++++++++++++++-- 5 files changed, 67 insertions(+), 6 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt index 968f77b20..3b4971d9c 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -6,7 +6,8 @@ package space.kscience.kmath.functions import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.operations.* +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.ScaleOperations import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.experimental.ExperimentalTypeInference @@ -269,6 +270,13 @@ public class LabeledPolynomialSpace>( } ) + /** + * Converts the integer [value] to polynomial. + */ + public override fun number(value: Int): LabeledPolynomial = + if (value == 0) zero + else LabeledPolynomial(mapOf(emptyMap() to constantNumber(value))) + public operator fun C.plus(other: Symbol): LabeledPolynomial = if (isZero()) LabeledPolynomial(mapOf( mapOf(other to 1U) to constantOne, diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt index b97c1e0b4..f886ca19f 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt @@ -5,7 +5,9 @@ package space.kscience.kmath.functions -import space.kscience.kmath.operations.* +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.ScaleOperations +import space.kscience.kmath.operations.invoke import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.experimental.ExperimentalTypeInference @@ -13,6 +15,7 @@ import kotlin.jvm.JvmName import kotlin.math.max import kotlin.math.min + /** * Polynomial model without fixation on specific context they are applied to. * @@ -193,6 +196,13 @@ public open class ListPolynomialSpace>( } ) + /** + * Converts the integer [value] to polynomial. + */ + public override fun number(value: Int): ListPolynomial = + if (value == 0) zero + else ListPolynomial(constantNumber(value)) + /** * Returns sum of the constant represented as polynomial and the polynomial. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index 3b9b907b7..387b6841d 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -5,7 +5,8 @@ package space.kscience.kmath.functions -import space.kscience.kmath.operations.* +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.ScaleOperations import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.experimental.ExperimentalTypeInference @@ -221,6 +222,13 @@ public open class NumberedPolynomialSpace>( } ) + /** + * Converts the integer [value] to polynomial. + */ + public override fun number(value: Int): NumberedPolynomial = + if (value == 0) zero + else NumberedPolynomial(mapOf(emptyList() to constantNumber(value))) + /** * Returns sum of the constant represented as polynomial and the polynomial. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index b26a57a34..dc46c868a 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -61,6 +61,11 @@ public interface PolynomialSpace> : Ring

{ */ public operator fun Int.times(other: C): C + /** + * Converts the integer [value] to constant. + */ + public fun constantNumber(value: Int): C = constantOne * value + /** * Returns sum of the polynomial and the integer represented as polynomial. * @@ -99,6 +104,11 @@ public interface PolynomialSpace> : Ring

{ */ public operator fun Int.times(other: P): P = multiplyBySquaring(other, this) + /** + * Converts the integer [value] to polynomial. + */ + public fun number(value: Int): P = one * value + /** * Returns the same constant. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index 635661b8a..724d88963 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -68,6 +68,11 @@ public interface RationalFunctionalSpace, R: RationalFunctio */ public operator fun Int.times(other: C): C + /** + * Converts the integer [value] to constant. + */ + public fun constantNumber(value: Int): C = constantOne * value + /** * Returns sum of the constant and the integer represented as polynomial. * @@ -106,6 +111,11 @@ public interface RationalFunctionalSpace, R: RationalFunctio */ public operator fun Int.times(other: P): P + /** + * Converts the integer [value] to polynomial. + */ + public fun polynomialNumber(value: Int): P = polynomialOne * value + /** * Returns sum of the rational function and the integer represented as rational function. * @@ -144,6 +154,11 @@ public interface RationalFunctionalSpace, R: RationalFunctio */ public operator fun Int.times(other: R): R = multiplyBySquaring(other, this) + /** + * Converts the integer [value] to rational function. + */ + public fun number(value: Int): R = one * value + /** * Returns the same constant. */ @@ -672,6 +687,11 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< */ 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) } + /** * Returns the same constant. */ @@ -880,7 +900,7 @@ public abstract class PolynomialSpaceOfFractions< P: Polynomial, R: RationalFunction, > : RationalFunctionalSpace { - protected abstract fun constructRationalFunction(numerator: P, denominator: P) : R + protected abstract fun constructRationalFunction(numerator: P, denominator: P = polynomialOne) : R /** * Returns sum of the rational function and the integer represented as rational function. @@ -944,6 +964,11 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) + /** + * Converts the integer [value] to rational function. + */ + public override fun number(value: Int): R = constructRationalFunction(polynomialNumber(value)) + /** * Returns sum of the constant represented as rational function and the rational function. */ @@ -1076,10 +1101,10 @@ public abstract class PolynomialSpaceOfFractions< /** * Instance of zero rational function (zero of the rational functions ring). */ - public override val zero: R get() = constructRationalFunction(polynomialZero, polynomialOne) + public override val zero: R get() = constructRationalFunction(polynomialZero) /** * Instance of unit polynomial (unit of the rational functions ring). */ - public override val one: R get() = constructRationalFunction(polynomialOne, polynomialOne) + public override val one: R get() = constructRationalFunction(polynomialOne) } \ No newline at end of file -- 2.34.1 From 2f9e5043577d798f1330c20da497bb44eb66c617 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 22 Mar 2022 13:58:29 +0300 Subject: [PATCH 056/275] Added division to RFs' Spaces. Added conversion to polynomial and RFs' spaces. Added requirements for RFs' denominators' changes for case of non-integral domain. Added requirements for non-zero divisor to RFs' divisions. --- .../kmath/functions/LabeledPolynomial.kt | 11 +- .../functions/LabeledRationalFunction.kt | 18 -- .../kmath/functions/ListPolynomial.kt | 13 +- .../kmath/functions/ListRationalFunction.kt | 24 -- .../kmath/functions/NumberedPolynomial.kt | 11 +- .../kscience/kmath/functions/Polynomial.kt | 17 ++ .../kmath/functions/RationalFunction.kt | 217 +++++++++++++++++- 7 files changed, 250 insertions(+), 61 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt index 3b4971d9c..e0b92a712 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -273,9 +273,7 @@ public class LabeledPolynomialSpace>( /** * Converts the integer [value] to polynomial. */ - public override fun number(value: Int): LabeledPolynomial = - if (value == 0) zero - else LabeledPolynomial(mapOf(emptyMap() to constantNumber(value))) + public override fun number(value: Int): LabeledPolynomial = number(constantNumber(value)) public operator fun C.plus(other: Symbol): LabeledPolynomial = if (isZero()) LabeledPolynomial(mapOf( @@ -425,6 +423,13 @@ public class LabeledPolynomialSpace>( } ) + /** + * Converts the constant [value] to polynomial. + */ + public override fun number(value: C): LabeledPolynomial = + if (value == 0) zero + else LabeledPolynomial(mapOf(emptyMap() to value)) + public operator fun Symbol.plus(other: Symbol): LabeledPolynomial = if (this == other) LabeledPolynomial(mapOf( mapOf(this to 1U) to constantOne * 2 diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt index f347f9191..735e04a48 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt @@ -144,24 +144,6 @@ public class LabeledRationalFunctionSpace>( // TODO: Разобрать - public operator fun LabeledRationalFunction.div(other: LabeledRationalFunction): LabeledRationalFunction = - LabeledRationalFunction( - numerator * other.denominator, - denominator * other.numerator - ) - - public operator fun LabeledRationalFunction.div(other: LabeledPolynomial): LabeledRationalFunction = - LabeledRationalFunction( - numerator, - denominator * other - ) - - public operator fun LabeledRationalFunction.div(other: C): LabeledRationalFunction = - LabeledRationalFunction( - numerator, - denominator * other - ) - // operator fun invoke(arg: Map): LabeledRationalFunction = // LabeledRationalFunction( // numerator(arg), diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt index f886ca19f..90e9cde69 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt @@ -66,7 +66,7 @@ public fun ListPolynomial(coefficients: List, reverse: Boolean = false): public fun ListPolynomial(vararg coefficients: C, reverse: Boolean = false): ListPolynomial = ListPolynomial(with(coefficients) { if (reverse) reversed() else toList() }) -public fun C.asPolynomial() : ListPolynomial = ListPolynomial(listOf(this)) +public fun C.asListPolynomial() : ListPolynomial = ListPolynomial(listOf(this)) /** * Space of univariate polynomials constructed over ring. @@ -199,9 +199,7 @@ public open class ListPolynomialSpace>( /** * Converts the integer [value] to polynomial. */ - public override fun number(value: Int): ListPolynomial = - if (value == 0) zero - else ListPolynomial(constantNumber(value)) + public override fun number(value: Int): ListPolynomial = number(constantNumber(value)) /** * Returns sum of the constant represented as polynomial and the polynomial. @@ -313,6 +311,13 @@ public open class ListPolynomialSpace>( } ) + /** + * Converts the constant [value] to polynomial. + */ + public override fun number(value: C): ListPolynomial = + if (value.isZero()) zero + else ListPolynomial(value) + /** * Returns negation of the polynomial. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt index 50ddd3118..8bd925c46 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt @@ -70,30 +70,6 @@ public class ListRationalFunctionSpace> ( // TODO: Разобрать - public operator fun ListRationalFunction.div(other: ListRationalFunction): ListRationalFunction = - ListRationalFunction( - numerator * other.denominator, - denominator * other.numerator - ) - - public operator fun ListRationalFunction.div(other: ListPolynomial): ListRationalFunction = - ListRationalFunction( - numerator, - denominator * other - ) - - public operator fun ListRationalFunction.div(other: C): ListRationalFunction = - ListRationalFunction( - numerator, - denominator * other - ) - - public operator fun ListRationalFunction.div(other: Int): ListRationalFunction = - ListRationalFunction( - numerator, - denominator * other - ) - // operator fun invoke(arg: UnivariatePolynomial): RationalFunction = // RationalFunction( // numerator(arg), diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index 387b6841d..1f37a1c2b 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -225,9 +225,7 @@ public open class NumberedPolynomialSpace>( /** * Converts the integer [value] to polynomial. */ - public override fun number(value: Int): NumberedPolynomial = - if (value == 0) zero - else NumberedPolynomial(mapOf(emptyList() to constantNumber(value))) + public override fun number(value: Int): NumberedPolynomial = number(constantNumber(value)) /** * Returns sum of the constant represented as polynomial and the polynomial. @@ -331,6 +329,13 @@ public open class NumberedPolynomialSpace>( } ) + /** + * Converts the constant [value] to polynomial. + */ + public override fun number(value: C): NumberedPolynomial = + if (value == 0) zero + else NumberedPolynomial(mapOf(emptyList() to value)) + /** * Returns negation of the polynomial. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index dc46c868a..f8d7d5a36 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -65,6 +65,10 @@ public interface PolynomialSpace> : Ring

{ * 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 polynomial. @@ -108,6 +112,10 @@ public interface PolynomialSpace> : Ring

{ * Converts the integer [value] to polynomial. */ public fun number(value: Int): P = one * value + /** + * Converts the integer to polynomial. + */ + public fun Int.asPolynomial(): P = number(this) /** * Returns the same constant. @@ -206,6 +214,15 @@ public interface PolynomialSpace> : Ring

{ */ 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. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index 724d88963..90e3bdbb1 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -72,6 +72,10 @@ public interface RationalFunctionalSpace, R: RationalFunctio * 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 polynomial. @@ -115,6 +119,10 @@ public interface RationalFunctionalSpace, R: RationalFunctio * 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 rational function. @@ -134,6 +142,13 @@ public interface RationalFunctionalSpace, R: RationalFunctio * The operation is equivalent to sum of [other] copies of [this]. */ public operator fun R.times(other: Int): R = multiplyBySquaring(this, other) + /** + * Returns quotient of the rational function and the integer represented as 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 / multiplyBySquaring(one, other) /** * Returns sum of the integer represented as rational function and the rational function. @@ -153,11 +168,22 @@ public interface RationalFunctionalSpace, R: RationalFunctio * The operation is equivalent to sum of [this] copies of [other]. */ public operator fun Int.times(other: R): R = multiplyBySquaring(other, this) + /** + * Returns quotient of the integer represented as 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 = multiplyBySquaring(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. @@ -256,6 +282,15 @@ public interface RationalFunctionalSpace, R: RationalFunctio */ 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. */ @@ -276,6 +311,10 @@ public interface RationalFunctionalSpace, R: RationalFunctio * Returns product of the polynomials. */ public operator fun P.times(other: P): P + /** + * Returns quotient of the polynomials as rational function. + */ + public operator fun P.div(other: P): R /** * Raises [arg] to the integer power [exponent]. */ @@ -336,19 +375,36 @@ public interface RationalFunctionalSpace, R: RationalFunctio * Returns product of the constant represented as polynomial and the rational function. */ public operator fun C.times(other: R): R + /** + * Returns quotient of the constant represented as polynomial and the rational function. + */ + public operator fun C.div(other: R): R /** - * Returns sum of the constant represented as rational function and the rational function. + * Returns sum of the rational function and the constant represented as rational function. */ public operator fun R.plus(other: C): R /** - * Returns difference between the constant represented as rational function and the rational function. + * Returns difference between the rational function and the constant represented as rational function. */ public operator fun R.minus(other: C): R /** - * Returns product of the constant represented as rational function and the rational function. + * Returns product of the rational function and the constant represented as rational function. */ public operator fun R.times(other: C): R + /** + * Returns quotient of the rational function and the constant represented as rational function. + */ + public operator fun R.div(other: C): R + + /** + * Converts the constant [value] to rational function. + */ + public fun number(value: C): R = one * value + /** + * Converts the constant to rational function. + */ + public fun C.asRationalFunction(): R = number(this) /** * Returns sum of the polynomial represented as rational function and the rational function. @@ -362,19 +418,36 @@ public interface RationalFunctionalSpace, R: RationalFunctio * Returns product of the polynomial represented as polynomial and the rational function. */ public operator fun P.times(other: R): R + /** + * Returns quotient of the polynomial represented as polynomial and the rational function. + */ + public operator fun P.div(other: R): R /** - * Returns sum of the polynomial represented as rational function and the rational function. + * Returns sum of the rational function and the polynomial represented as rational function. */ public operator fun R.plus(other: P): R /** - * Returns difference between the polynomial represented as rational function and the rational function. + * Returns difference between the rational function and the polynomial represented as rational function. */ public operator fun R.minus(other: P): R /** - * Returns product of the polynomial represented as rational function and the rational function. + * Returns product of the rational function and the polynomial represented as rational function. */ public operator fun R.times(other: P): R + /** + * Returns quotient of the rational function and the polynomial represented as rational function. + */ + public operator fun R.div(other: P): R + + /** + * Converts the polynomial [value] to rational function. + */ + public fun number(value: P): R = one * value + /** + * Converts the polynomial to rational function. + */ + public fun P.asRationalFunction(): R = number(this) /** * Returns the same rational function. @@ -396,6 +469,10 @@ public interface RationalFunctionalSpace, R: RationalFunctio * 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]. */ @@ -649,6 +726,15 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< */ 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 polynomial. * @@ -691,6 +777,10 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< * 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. @@ -783,6 +873,15 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< */ 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. */ @@ -933,6 +1032,19 @@ public abstract class PolynomialSpaceOfFractions< denominator ) + public override operator fun R.div(other: Int): R { + val otherAsConstant = constantNumber(other) + require(otherAsConstant.isNotZero()) { "/ by zero." } + return constructRationalFunction( + numerator, + (denominator * other).also { + check(it.isNotZero()) { + "Got zero denominator during division of rational functions to constant. It means underlying ring of polynomials is not integral domain." + } + } + ) + } + /** * Returns sum of the integer represented as rational function and the rational function. * @@ -964,11 +1076,24 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) + public override operator fun Int.div(other: R): R { + require(other.numerator.isNotZero()) { "/ by zero." } + return 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. + */ + public override operator fun P.div(other: P): R = constructRationalFunction(this, other) + /** * Returns sum of the constant represented as rational function and the rational function. */ @@ -994,6 +1119,14 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) + public override operator fun C.div(other: R): R { + require(other.numerator.isNotZero()) { "/ by zero." } + return constructRationalFunction( + this * other.denominator, + other.numerator + ) + } + /** * Returns sum of the constant represented as rational function and the rational function. */ @@ -1019,6 +1152,23 @@ public abstract class PolynomialSpaceOfFractions< denominator ) + public override operator fun R.div(other: C): R { + require(other.isNotZero()) { "/ by zero." } + return constructRationalFunction( + numerator, + (denominator * other).also { + check(it.isNotZero()) { + "Got zero denominator during division of rational functions to constant. It means underlying ring of polynomials is not integral domain." + } + } + ) + } + + /** + * Converts the constant [value] to rational function. + */ + public override fun number(value: C): R = constructRationalFunction(polynomialNumber(value)) + /** * Returns sum of the polynomial represented as rational function and the rational function. */ @@ -1044,6 +1194,14 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) + public override operator fun P.div(other: R): R { + require(other.numerator.isNotZero()) { "/ by zero." } + return constructRationalFunction( + this * other.denominator, + other.numerator + ) + } + /** * Returns sum of the polynomial represented as rational function and the rational function. */ @@ -1069,6 +1227,23 @@ public abstract class PolynomialSpaceOfFractions< denominator ) + public override operator fun R.div(other: P): R { + require(other.isNotZero()) { "/ by zero." } + return constructRationalFunction( + numerator, + (denominator * other).also { + require(it.isNotZero()) { + "Got zero denominator during division of rational functions to polynomial. It means underlying ring of polynomials is not integral domain." + } + } + ) + } + + /** + * Converts the polynomial [value] to rational function. + */ + public override fun number(value: P): R = constructRationalFunction(value) + /** * Returns negation of the rational function. */ @@ -1079,7 +1254,11 @@ public abstract class PolynomialSpaceOfFractions< public override operator fun R.plus(other: R): R = constructRationalFunction( numerator * other.denominator + denominator * other.numerator, - denominator * other.denominator + (denominator * other.denominator).also { + check(it.isNotZero()) { + "Got zero denominator during addition of rational functions. It means underlying ring of polynomials is not integral domain." + } + } ) /** * Returns difference of the rational functions. @@ -1087,7 +1266,11 @@ public abstract class PolynomialSpaceOfFractions< public override operator fun R.minus(other: R): R = constructRationalFunction( numerator * other.denominator - denominator * other.numerator, - denominator * other.denominator + (denominator * other.denominator).also { + check(it.isNotZero()) { + "Got zero denominator during subtraction of rational functions. It means underlying ring of polynomials is not integral domain." + } + } ) /** * Returns product of the rational functions. @@ -1095,9 +1278,25 @@ public abstract class PolynomialSpaceOfFractions< public override operator fun R.times(other: R): R = constructRationalFunction( numerator * other.numerator, - denominator * other.denominator + (denominator * other.denominator).also { + check(it.isNotZero()) { + "Got zero denominator during multiplication of rational functions. It means underlying ring of polynomials is not integral domain." + } + } ) + public override operator fun R.div(other: R): R { + require(other.isNotZero()) { "/ by zero." } + return constructRationalFunction( + numerator * other.denominator, + (denominator * other.numerator).also { + check(it.isNotZero()) { + "Got zero denominator during division of rational functions. It means underlying ring of polynomials is not integral domain." + } + } + ) + } + /** * Instance of zero rational function (zero of the rational functions ring). */ -- 2.34.1 From 39ce855075662461892ff70f2c52c630d9e70d66 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 22 Mar 2022 14:25:09 +0300 Subject: [PATCH 057/275] Added constructors for RFs' spaces --- .../functions/LabeledRationalFunction.kt | 82 +++++++------- .../kmath/functions/ListRationalFunction.kt | 62 +++++++---- .../functions/NumberedRationalFunction.kt | 100 ++++++++---------- 3 files changed, 122 insertions(+), 122 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt index 735e04a48..599660b52 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt @@ -19,48 +19,46 @@ public class LabeledRationalFunction( // Waiting for context receivers :( TODO: Replace with context receivers when they will be available -//context(RationalFunctionSpace) -//@Suppress("FunctionName") -//internal fun > RationalFunction(numerator: Polynomial, denominator: Polynomial): RationalFunction = -// if (denominator.isZero()) throw ArithmeticException("/ by zero") -// else RationalFunction(numerator, denominator) -//context(RationalFunctionSpace) -//@Suppress("FunctionName") -//public fun > RationalFunction(numeratorCoefficients: List, denominatorCoefficients: List, reverse: Boolean = false): RationalFunction = -// RationalFunction( -// Polynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), -// Polynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } ).also { if (it.isZero()) } -// ) -//context(RationalFunctionSpace) -//@Suppress("FunctionName") -//public fun > RationalFunction(numerator: Polynomial): RationalFunction = -// RationalFunction(numerator, onePolynomial) -//context(RationalFunctionSpace) -//@Suppress("FunctionName") -//public fun > RationalFunction(numeratorCoefficients: List, reverse: Boolean = false): RationalFunction = -// RationalFunction( -// Polynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ) -// ) - -// TODO: Rewrite former constructors as fabrics -//constructor(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>) : this( -//LabeledPolynomial(numeratorCoefficients), -//LabeledPolynomial(denominatorCoefficients) -//) -// -//constructor(numeratorCoefficients: Collection, C>>, denominatorCoefficients: Collection, C>>) : this( -//LabeledPolynomial(numeratorCoefficients), -//LabeledPolynomial(denominatorCoefficients) -//) -// -//constructor(numerator: LabeledPolynomial) : this(numerator, numerator.getOne()) -//constructor(numeratorCoefficients: Map, C>) : this( -//LabeledPolynomial(numeratorCoefficients) -//) -// -//constructor(numeratorCoefficients: Collection, C>>) : this( -//LabeledPolynomial(numeratorCoefficients) -//) +@Suppress("FunctionName") +internal fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numerator: LabeledPolynomial, denominator: LabeledPolynomial): LabeledRationalFunction = + if (denominator.isZero()) throw ArithmeticException("/ by zero") + else LabeledRationalFunction(numerator, denominator) +@Suppress("FunctionName") +internal fun > A.LabeledRationalFunction(numerator: LabeledPolynomial, denominator: LabeledPolynomial): LabeledRationalFunction = + if (denominator.coefficients.values.all { it == zero }) throw ArithmeticException("/ by zero") + else LabeledRationalFunction(numerator, denominator) +@Suppress("FunctionName") +public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): LabeledRationalFunction = + if (denominatorCoefficients.values.all { it == zero }) throw ArithmeticException("/ by zero") + else LabeledRationalFunction( + LabeledPolynomial(numeratorCoefficients), + LabeledPolynomial(denominatorCoefficients) + ) +@Suppress("FunctionName") +public fun > A.LabeledRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): LabeledRationalFunction = + if (denominatorCoefficients.values.all { it == zero }) throw ArithmeticException("/ by zero") + else LabeledRationalFunction( + LabeledPolynomial(numeratorCoefficients), + LabeledPolynomial(denominatorCoefficients) + ) +@Suppress("FunctionName") +public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numerator: LabeledPolynomial): LabeledRationalFunction = + LabeledRationalFunction(numerator, polynomialOne) +@Suppress("FunctionName") +public fun > A.LabeledRationalFunction(numerator: LabeledPolynomial): LabeledRationalFunction = + LabeledRationalFunction(numerator, LabeledPolynomial(mapOf(emptyMap() to one))) +@Suppress("FunctionName") +public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numeratorCoefficients: Map, C>): LabeledRationalFunction = + LabeledRationalFunction( + LabeledPolynomial(numeratorCoefficients), + polynomialOne + ) +@Suppress("FunctionName") +public fun > A.LabeledRationalFunction(numeratorCoefficients: Map, C>): LabeledRationalFunction = + LabeledRationalFunction( + LabeledPolynomial(numeratorCoefficients), + LabeledPolynomial(mapOf(emptyMap() to one)) + ) public class LabeledRationalFunctionSpace>( public val ring: A, diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt index 8bd925c46..67c7e9fa2 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt @@ -17,28 +17,46 @@ public data class ListRationalFunction internal constructor ( // Waiting for context receivers :( TODO: Replace with context receivers when they will be available -//context(RationalFunctionSpace) -//@Suppress("FunctionName") -//internal fun > RationalFunction(numerator: Polynomial, denominator: Polynomial): RationalFunction = -// if (denominator.isZero()) throw ArithmeticException("/ by zero") -// else RationalFunction(numerator, denominator) -//context(RationalFunctionSpace) -//@Suppress("FunctionName") -//public fun > RationalFunction(numeratorCoefficients: List, denominatorCoefficients: List, reverse: Boolean = false): RationalFunction = -// RationalFunction( -// Polynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), -// Polynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } ).also { if (it.isZero()) } -// ) -//context(RationalFunctionSpace) -//@Suppress("FunctionName") -//public fun > RationalFunction(numerator: Polynomial): RationalFunction = -// RationalFunction(numerator, onePolynomial) -//context(RationalFunctionSpace) -//@Suppress("FunctionName") -//public fun > RationalFunction(numeratorCoefficients: List, reverse: Boolean = false): RationalFunction = -// RationalFunction( -// Polynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ) -// ) +@Suppress("FunctionName") +internal fun > ListRationalFunctionSpace.ListRationalFunction(numerator: ListPolynomial, denominator: ListPolynomial): ListRationalFunction = + if (denominator.isZero()) throw ArithmeticException("/ by zero") + else ListRationalFunction(numerator, denominator) +@Suppress("FunctionName") +internal fun > A.ListRationalFunction(numerator: ListPolynomial, denominator: ListPolynomial): ListRationalFunction = + if (denominator.coefficients.all { it == zero }) throw ArithmeticException("/ by zero") + else ListRationalFunction(numerator, denominator) +@Suppress("FunctionName") +public fun > ListRationalFunctionSpace.ListRationalFunction(numeratorCoefficients: List, denominatorCoefficients: List, reverse: Boolean = false): ListRationalFunction = + if (denominatorCoefficients.all { it == zero }) throw ArithmeticException("/ by zero") + else ListRationalFunction( + ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), + ListPolynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } ) + ) +@Suppress("FunctionName") +public fun > A.ListRationalFunction(numeratorCoefficients: List, denominatorCoefficients: List, reverse: Boolean = false): ListRationalFunction = + if (denominatorCoefficients.all { it == zero }) throw ArithmeticException("/ by zero") + else ListRationalFunction( + ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), + ListPolynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } ) + ) +@Suppress("FunctionName") +public fun > ListRationalFunctionSpace.ListRationalFunction(numerator: ListPolynomial): ListRationalFunction = + ListRationalFunction(numerator, polynomialOne) +@Suppress("FunctionName") +public fun > A.ListRationalFunction(numerator: ListPolynomial): ListRationalFunction = + ListRationalFunction(numerator, ListPolynomial(listOf(one))) +@Suppress("FunctionName") +public fun > ListRationalFunctionSpace.ListRationalFunction(numeratorCoefficients: List, reverse: Boolean = false): ListRationalFunction = + ListRationalFunction( + ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), + polynomialOne + ) +@Suppress("FunctionName") +public fun > A.ListRationalFunction(numeratorCoefficients: List, reverse: Boolean = false): ListRationalFunction = + ListRationalFunction( + ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), + ListPolynomial(listOf(one)) + ) public class ListRationalFunctionSpace> ( public val ring: A, diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt index f3b90b5c5..b32f01f2a 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt @@ -5,7 +5,8 @@ package space.kscience.kmath.functions -import space.kscience.kmath.operations.* +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.invoke import kotlin.math.max @@ -18,45 +19,46 @@ public class NumberedRationalFunction internal constructor( // Waiting for context receivers :( TODO: Replace with context receivers when they will be available -//context(RationalFunctionSpace) -//@Suppress("FunctionName") -//internal fun > RationalFunction(numerator: Polynomial, denominator: Polynomial): RationalFunction = -// if (denominator.isZero()) throw ArithmeticException("/ by zero") -// else RationalFunction(numerator, denominator) -//context(RationalFunctionSpace) -//@Suppress("FunctionName") -//public fun > RationalFunction(numeratorCoefficients: List, denominatorCoefficients: List, reverse: Boolean = false): RationalFunction = -// RationalFunction( -// Polynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), -// Polynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } ).also { if (it.isZero()) } -// ) -//context(RationalFunctionSpace) -//@Suppress("FunctionName") -//public fun > RationalFunction(numerator: Polynomial): RationalFunction = -// RationalFunction(numerator, onePolynomial) -//context(RationalFunctionSpace) -//@Suppress("FunctionName") -//public fun > RationalFunction(numeratorCoefficients: List, reverse: Boolean = false): RationalFunction = -// RationalFunction( -// Polynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ) -// ) - -// TODO: Rewrite former constructors as fabrics -//constructor(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>) : this( -//Polynomial(numeratorCoefficients), -//Polynomial(denominatorCoefficients) -//) -//constructor(numeratorCoefficients: Collection, C>>, denominatorCoefficients: Collection, C>>) : this( -//Polynomial(numeratorCoefficients), -//Polynomial(denominatorCoefficients) -//) -//constructor(numerator: Polynomial) : this(numerator, numerator.getOne()) -//constructor(numeratorCoefficients: Map, C>) : this( -//Polynomial(numeratorCoefficients) -//) -//constructor(numeratorCoefficients: Collection, C>>) : this( -//Polynomial(numeratorCoefficients) -//) +@Suppress("FunctionName") +internal fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numerator: NumberedPolynomial, denominator: NumberedPolynomial): NumberedRationalFunction = + if (denominator.isZero()) throw ArithmeticException("/ by zero") + else NumberedRationalFunction(numerator, denominator) +@Suppress("FunctionName") +internal fun > A.NumberedRationalFunction(numerator: NumberedPolynomial, denominator: NumberedPolynomial): NumberedRationalFunction = + if (denominator.coefficients.values.all { it == zero }) throw ArithmeticException("/ by zero") + else NumberedRationalFunction(numerator, denominator) +@Suppress("FunctionName") +public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): NumberedRationalFunction = + if (denominatorCoefficients.values.all { it == zero }) throw ArithmeticException("/ by zero") + else NumberedRationalFunction( + NumberedPolynomial(numeratorCoefficients), + NumberedPolynomial(denominatorCoefficients) + ) +@Suppress("FunctionName") +public fun > A.NumberedRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): NumberedRationalFunction = + if (denominatorCoefficients.values.all { it == zero }) throw ArithmeticException("/ by zero") + else NumberedRationalFunction( + NumberedPolynomial(numeratorCoefficients), + NumberedPolynomial(denominatorCoefficients) + ) +@Suppress("FunctionName") +public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numerator: NumberedPolynomial): NumberedRationalFunction = + NumberedRationalFunction(numerator, polynomialOne) +@Suppress("FunctionName") +public fun > A.NumberedRationalFunction(numerator: NumberedPolynomial): NumberedRationalFunction = + NumberedRationalFunction(numerator, NumberedPolynomial(mapOf(emptyList() to one))) +@Suppress("FunctionName") +public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numeratorCoefficients: Map, C>): NumberedRationalFunction = + NumberedRationalFunction( + NumberedPolynomial(numeratorCoefficients), + polynomialOne + ) +@Suppress("FunctionName") +public fun > A.NumberedRationalFunction(numeratorCoefficients: Map, C>): NumberedRationalFunction = + NumberedRationalFunction( + NumberedPolynomial(numeratorCoefficients), + NumberedPolynomial(mapOf(emptyList() to one)) + ) public class NumberedRationalFunctionSpace> ( public val ring: A, @@ -156,24 +158,6 @@ public class NumberedRationalFunctionSpace> ( // TODO: Разобрать - public operator fun NumberedRationalFunction.div(other: NumberedRationalFunction): NumberedRationalFunction = - NumberedRationalFunction( - numerator * other.denominator, - denominator * other.numerator - ) - - public operator fun NumberedRationalFunction.div(other: NumberedPolynomial): NumberedRationalFunction = - NumberedRationalFunction( - numerator, - denominator * other - ) - - public operator fun NumberedRationalFunction.div(other: C): NumberedRationalFunction = - NumberedRationalFunction( - numerator, - denominator * other - ) - // operator fun invoke(arg: Map): NumberedRationalFunction = // NumberedRationalFunction( // numerator(arg), -- 2.34.1 From b44c99c265d0d8a43679c694135585047a489813 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 22 Mar 2022 15:28:34 +0300 Subject: [PATCH 058/275] Added multivariate abstractions. --- .../kmath/functions/LabeledPolynomial.kt | 68 +++--- .../functions/LabeledRationalFunction.kt | 33 +-- .../kscience/kmath/functions/Polynomial.kt | 60 +++++- .../kmath/functions/RationalFunction.kt | 197 ++++++++++++++++++ 4 files changed, 303 insertions(+), 55 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt index e0b92a712..29aeb6bb0 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -117,8 +117,8 @@ public fun C.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomia */ public class LabeledPolynomialSpace>( public override val ring: A, -) : PolynomialSpaceOverRing, A> { - public operator fun Symbol.plus(other: Int): LabeledPolynomial = +) : MultivariatePolynomialSpace>, PolynomialSpaceOverRing, A> { + public override operator fun Symbol.plus(other: Int): LabeledPolynomial = if (other == 0) LabeledPolynomial(mapOf( mapOf(this@plus to 1U) to constantOne, )) @@ -126,7 +126,7 @@ public class LabeledPolynomialSpace>( mapOf(this@plus to 1U) to constantOne, emptyMap() to constantOne * other, )) - public operator fun Symbol.minus(other: Int): LabeledPolynomial = + public override operator fun Symbol.minus(other: Int): LabeledPolynomial = if (other == 0) LabeledPolynomial(mapOf( mapOf(this@minus to 1U) to -constantOne, )) @@ -134,13 +134,13 @@ public class LabeledPolynomialSpace>( mapOf(this@minus to 1U) to -constantOne, emptyMap() to constantOne * other, )) - public operator fun Symbol.times(other: Int): LabeledPolynomial = + public override operator fun Symbol.times(other: Int): LabeledPolynomial = if (other == 0) zero else LabeledPolynomial(mapOf( mapOf(this to 1U) to constantOne * other, )) - public operator fun Int.plus(other: Symbol): LabeledPolynomial = + public override operator fun Int.plus(other: Symbol): LabeledPolynomial = if (this == 0) LabeledPolynomial(mapOf( mapOf(other to 1U) to constantOne, )) @@ -148,7 +148,7 @@ public class LabeledPolynomialSpace>( mapOf(other to 1U) to constantOne, emptyMap() to constantOne * this@plus, )) - public operator fun Int.minus(other: Symbol): LabeledPolynomial = + public override operator fun Int.minus(other: Symbol): LabeledPolynomial = if (this == 0) LabeledPolynomial(mapOf( mapOf(other to 1U) to -constantOne, )) @@ -156,7 +156,7 @@ public class LabeledPolynomialSpace>( mapOf(other to 1U) to -constantOne, emptyMap() to constantOne * this@minus, )) - public operator fun Int.times(other: Symbol): LabeledPolynomial = + public override operator fun Int.times(other: Symbol): LabeledPolynomial = if (this == 0) zero else LabeledPolynomial(mapOf( mapOf(other to 1U) to constantOne * this@times, @@ -275,7 +275,7 @@ public class LabeledPolynomialSpace>( */ public override fun number(value: Int): LabeledPolynomial = number(constantNumber(value)) - public operator fun C.plus(other: Symbol): LabeledPolynomial = + public override operator fun C.plus(other: Symbol): LabeledPolynomial = if (isZero()) LabeledPolynomial(mapOf( mapOf(other to 1U) to constantOne, )) @@ -283,7 +283,7 @@ public class LabeledPolynomialSpace>( mapOf(other to 1U) to constantOne, emptyMap() to this@plus, )) - public operator fun C.minus(other: Symbol): LabeledPolynomial = + public override operator fun C.minus(other: Symbol): LabeledPolynomial = if (isZero()) LabeledPolynomial(mapOf( mapOf(other to 1U) to -constantOne, )) @@ -291,13 +291,13 @@ public class LabeledPolynomialSpace>( mapOf(other to 1U) to -constantOne, emptyMap() to this@minus, )) - public operator fun C.times(other: Symbol): LabeledPolynomial = + public override operator fun C.times(other: Symbol): LabeledPolynomial = if (isZero()) zero else LabeledPolynomial(mapOf( mapOf(other to 1U) to this@times, )) - public operator fun Symbol.plus(other: C): LabeledPolynomial = + public override operator fun Symbol.plus(other: C): LabeledPolynomial = if (other.isZero()) LabeledPolynomial(mapOf( mapOf(this@plus to 1U) to constantOne, )) @@ -305,7 +305,7 @@ public class LabeledPolynomialSpace>( mapOf(this@plus to 1U) to constantOne, emptyMap() to other, )) - public operator fun Symbol.minus(other: C): LabeledPolynomial = + public override operator fun Symbol.minus(other: C): LabeledPolynomial = if (other.isZero()) LabeledPolynomial(mapOf( mapOf(this@minus to 1U) to -constantOne, )) @@ -313,7 +313,7 @@ public class LabeledPolynomialSpace>( mapOf(this@minus to 1U) to -constantOne, emptyMap() to other, )) - public operator fun Symbol.times(other: C): LabeledPolynomial = + public override operator fun Symbol.times(other: C): LabeledPolynomial = if (other.isZero()) zero else LabeledPolynomial(mapOf( mapOf(this@times to 1U) to other, @@ -430,7 +430,15 @@ public class LabeledPolynomialSpace>( if (value == 0) zero else LabeledPolynomial(mapOf(emptyMap() to value)) - public operator fun Symbol.plus(other: Symbol): LabeledPolynomial = + public override operator fun Symbol.unaryPlus(): LabeledPolynomial = + LabeledPolynomial(mapOf( + mapOf(this to 1U) to constantOne, + )) + public override operator fun Symbol.unaryMinus(): LabeledPolynomial = + LabeledPolynomial(mapOf( + mapOf(this to 1U) to -constantOne, + )) + public override operator fun Symbol.plus(other: Symbol): LabeledPolynomial = if (this == other) LabeledPolynomial(mapOf( mapOf(this to 1U) to constantOne * 2 )) @@ -438,13 +446,13 @@ public class LabeledPolynomialSpace>( mapOf(this to 1U) to constantOne, mapOf(other to 1U) to constantOne, )) - public operator fun Symbol.minus(other: Symbol): LabeledPolynomial = + public override operator fun Symbol.minus(other: Symbol): LabeledPolynomial = if (this == other) zero else LabeledPolynomial(mapOf( mapOf(this to 1U) to constantOne, mapOf(other to 1U) to -constantOne, )) - public operator fun Symbol.times(other: Symbol): LabeledPolynomial = + public override operator fun Symbol.times(other: Symbol): LabeledPolynomial = if (this == other) LabeledPolynomial(mapOf( mapOf(this to 2U) to constantOne )) @@ -452,7 +460,7 @@ public class LabeledPolynomialSpace>( mapOf(this to 1U, other to 1U) to constantOne, )) - public operator fun Symbol.plus(other: LabeledPolynomial): LabeledPolynomial = + public override operator fun Symbol.plus(other: LabeledPolynomial): LabeledPolynomial = with(other.coefficients) { if (isEmpty()) LabeledPolynomial(mapOf(mapOf(this@plus to 1u) to constantOne)) else LabeledPolynomial( @@ -467,7 +475,7 @@ public class LabeledPolynomialSpace>( } ) } - public operator fun Symbol.minus(other: LabeledPolynomial): LabeledPolynomial = + public override operator fun Symbol.minus(other: LabeledPolynomial): LabeledPolynomial = with(other.coefficients) { if (isEmpty()) LabeledPolynomial(mapOf(mapOf(this@minus to 1u) to constantOne)) else LabeledPolynomial( @@ -484,13 +492,13 @@ public class LabeledPolynomialSpace>( } ) } - public operator fun Symbol.times(other: LabeledPolynomial): LabeledPolynomial = + public override operator fun Symbol.times(other: LabeledPolynomial): LabeledPolynomial = LabeledPolynomial( other.coefficients .mapKeys { (degs, _) -> degs.toMutableMap().also{ it[this] = if (this in it) it[this]!! + 1U else 1U } } ) - public operator fun LabeledPolynomial.plus(other: Symbol): LabeledPolynomial = + public override operator fun LabeledPolynomial.plus(other: Symbol): LabeledPolynomial = with(coefficients) { if (isEmpty()) LabeledPolynomial(mapOf(mapOf(other to 1u) to constantOne)) else LabeledPolynomial( @@ -505,7 +513,7 @@ public class LabeledPolynomialSpace>( } ) } - public operator fun LabeledPolynomial.minus(other: Symbol): LabeledPolynomial = + public override operator fun LabeledPolynomial.minus(other: Symbol): LabeledPolynomial = with(coefficients) { if (isEmpty()) LabeledPolynomial(mapOf(mapOf(other to 1u) to constantOne)) else LabeledPolynomial( @@ -520,7 +528,7 @@ public class LabeledPolynomialSpace>( } ) } - public operator fun LabeledPolynomial.times(other: Symbol): LabeledPolynomial = + public override operator fun LabeledPolynomial.times(other: Symbol): LabeledPolynomial = LabeledPolynomial( coefficients .mapKeys { (degs, _) -> degs.toMutableMap().also{ it[other] = if (other in it) it[other]!! + 1U else 1U } } @@ -604,7 +612,7 @@ public class LabeledPolynomialSpace>( * 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 LabeledPolynomial.degrees: Map + public override val LabeledPolynomial.degrees: Map get() = buildMap { coefficients.entries.forEach { (degs, c) -> @@ -613,10 +621,20 @@ public class LabeledPolynomialSpace>( } } } + /** + * Counts degree of the polynomial by the specified [variable]. + */ + public override fun LabeledPolynomial.degreeBy(variable: Symbol): UInt = + coefficients.entries.maxOfOrNull { (degs, c) -> if (c.isZero()) 0u else 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, c) -> if (c.isZero()) 0u else degs.filterKeys { it in variables }.values.sum() } ?: 0u /** * Set of all variables that appear in the polynomial in positive exponents. */ - public val LabeledPolynomial.variables: Set + public override val LabeledPolynomial.variables: Set get() = buildSet { coefficients.entries.forEach { (degs, c) -> if (c.isNotZero()) addAll(degs.keys) } @@ -624,7 +642,7 @@ public class LabeledPolynomialSpace>( /** * Count of all variables that appear in the polynomial in positive exponents. */ - public val LabeledPolynomial.countOfVariables: Int get() = variables.size + public override val LabeledPolynomial.countOfVariables: Int get() = variables.size /** * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt index 599660b52..00dd3bb47 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt @@ -63,14 +63,16 @@ public fun > A.LabeledRationalFunction(numeratorCoefficients: Map< public class LabeledRationalFunctionSpace>( public val ring: A, ) : - RationalFunctionalSpaceOverPolynomialSpace< + MultivariateRationalFunctionalSpaceOverMultivariatePolynomialSpace< C, + Symbol, LabeledPolynomial, LabeledRationalFunction, LabeledPolynomialSpace, >, - PolynomialSpaceOfFractions< + MultivariatePolynomialSpaceOfFractions< C, + Symbol, LabeledPolynomial, LabeledRationalFunction, >() { @@ -113,33 +115,6 @@ public class LabeledRationalFunctionSpace>( return numerator * other.denominator equalsTo other.numerator * denominator } - /** - * 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 LabeledPolynomial.degrees: Map get() = polynomialRing { degrees } - /** - * Set of all variables that appear in the polynomial in positive exponents. - */ - public val LabeledPolynomial.variables: Set get() = polynomialRing { variables } - /** - * Count of all variables that appear in the polynomial in positive exponents. - */ - public val LabeledPolynomial.countOfVariables: Int get() = polynomialRing { countOfVariables } - - /** - * Count of all variables that appear in the polynomial in positive exponents. - */ - public val LabeledRationalFunction.variables: Set - get() = numerator.variables union denominator.variables - /** - * Count of all variables that appear in the polynomial in positive exponents. - */ - public val LabeledRationalFunction.countOfVariables: Int get() = variables.size - // TODO: Разобрать // operator fun invoke(arg: Map): LabeledRationalFunction = diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index f8d7d5a36..224e18832 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -5,7 +5,8 @@ package space.kscience.kmath.functions -import space.kscience.kmath.operations.* +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.invoke import kotlin.js.JsName import kotlin.jvm.JvmName @@ -413,4 +414,61 @@ public interface PolynomialSpaceOverRing, A: Ring> : Poly * Instance of unit constant (unit of the underlying ring). */ public override val constantOne: C get() = ring.one +} + +public interface MultivariatePolynomialSpace>: PolynomialSpace { + public operator fun V.plus(other: Int): P + public operator fun V.minus(other: Int): P + public operator fun V.times(other: Int): P + + public operator fun Int.plus(other: V): P + public operator fun Int.minus(other: V): P + public operator fun Int.times(other: V): P + + public operator fun C.plus(other: V): P + public operator fun C.minus(other: V): P + public operator fun C.times(other: V): P + + public operator fun V.plus(other: C): P + public operator fun V.minus(other: C): P + public operator fun V.times(other: C): P + + public operator fun V.unaryPlus(): P + public operator fun V.unaryMinus(): P + public operator fun V.plus(other: V): P + public operator fun V.minus(other: V): P + public operator fun V.times(other: V): P + + public operator fun V.plus(other: P): P + public operator fun V.minus(other: P): P + public operator fun V.times(other: P): P + + public operator fun P.plus(other: V): P + public operator fun P.minus(other: V): P + 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-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index 90e3bdbb1..c5fcde8ed 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -1306,4 +1306,201 @@ public abstract class PolynomialSpaceOfFractions< * Instance of unit polynomial (unit of the rational functions ring). */ public override val one: R get() = constructRationalFunction(polynomialOne) +} + +public interface MultivariateRationalFunctionalSpace< + C, + V, + P: Polynomial, + R: RationalFunction + >: RationalFunctionalSpace { + public operator fun V.plus(other: Int): P + public operator fun V.minus(other: Int): P + public operator fun V.times(other: Int): P + + public operator fun Int.plus(other: V): P + public operator fun Int.minus(other: V): P + public operator fun Int.times(other: V): P + + public operator fun C.plus(other: V): P + public operator fun C.minus(other: V): P + public operator fun C.times(other: V): P + + public operator fun V.plus(other: C): P + public operator fun V.minus(other: C): P + public operator fun V.times(other: C): P + + public operator fun V.unaryPlus(): P + public operator fun V.unaryMinus(): P + public operator fun V.plus(other: V): P + public operator fun V.minus(other: V): P + public operator fun V.times(other: V): P + + public operator fun V.plus(other: P): P + public operator fun V.minus(other: P): P + public operator fun V.times(other: P): P + + public operator fun P.plus(other: V): P + public operator fun P.minus(other: V): P + public operator fun P.times(other: V): P + + public operator fun V.plus(other: R): R + public operator fun V.minus(other: R): R + public operator fun V.times(other: R): R + + public operator fun R.plus(other: V): R + public operator fun R.minus(other: V): R + 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 +} + +public interface MultivariateRationalFunctionalSpaceOverRing< + C, + V, + P: Polynomial, + R: RationalFunction, + A: Ring + > : RationalFunctionalSpaceOverRing, MultivariateRationalFunctionalSpace + +public interface MultivariateRationalFunctionalSpaceOverPolynomialSpace< + C, + V, + P: Polynomial, + R: RationalFunction, + AP: PolynomialSpace, + > : RationalFunctionalSpaceOverPolynomialSpace, MultivariateRationalFunctionalSpace + +public interface MultivariateRationalFunctionalSpaceOverMultivariatePolynomialSpace< + C, + V, + P: Polynomial, + R: RationalFunction, + AP: MultivariatePolynomialSpace, + > : MultivariateRationalFunctionalSpaceOverPolynomialSpace { + public override operator fun V.plus(other: Int): P = polynomialRing { this@plus + other } + public override operator fun V.minus(other: Int): P = polynomialRing { this@minus - other } + public override operator fun V.times(other: Int): P = polynomialRing { this@times * other } + + public override operator fun Int.plus(other: V): P = polynomialRing { this@plus + other } + public override operator fun Int.minus(other: V): P = polynomialRing { this@minus - other } + public override operator fun Int.times(other: V): P = polynomialRing { this@times * other } + + public override operator fun C.plus(other: V): P = polynomialRing { this@plus + other } + public override operator fun C.minus(other: V): P = polynomialRing { this@minus - other } + public override operator fun C.times(other: V): P = polynomialRing { this@times * other } + + public override operator fun V.plus(other: C): P = polynomialRing { this@plus + other } + public override operator fun V.minus(other: C): P = polynomialRing { this@minus - other } + public override operator fun V.times(other: C): P = polynomialRing { this@times * other } + + public override operator fun V.unaryPlus(): P = polynomialRing { +this@unaryPlus } + public override operator fun V.unaryMinus(): P = polynomialRing { -this@unaryMinus } + public override operator fun V.plus(other: V): P = polynomialRing { this@plus + other } + public override operator fun V.minus(other: V): P = polynomialRing { this@minus - other } + public override operator fun V.times(other: V): P = polynomialRing { this@times * other } + + public override operator fun V.plus(other: P): P = polynomialRing { this@plus + other } + public override operator fun V.minus(other: P): P = polynomialRing { this@minus - other } + public override operator fun V.times(other: P): P = polynomialRing { this@times * other } + + public override operator fun P.plus(other: V): P = polynomialRing { this@plus + other } + public override operator fun P.minus(other: V): P = polynomialRing { this@minus - other } + 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 } +} + +public abstract class MultivariatePolynomialSpaceOfFractions< + C, + V, + P: Polynomial, + R: RationalFunction, + > : MultivariateRationalFunctionalSpace, PolynomialSpaceOfFractions() { + public override operator fun V.plus(other: R): R = + constructRationalFunction( + this * other.denominator + other.numerator, + other.denominator + ) + public override operator fun V.minus(other: R): R = + constructRationalFunction( + this * other.denominator - other.numerator, + other.denominator + ) + public override operator fun V.times(other: R): R = + constructRationalFunction( + this * other.numerator, + other.denominator + ) + + public override operator fun R.plus(other: V): R = + constructRationalFunction( + numerator + denominator * other, + denominator + ) + public override operator fun R.minus(other: V): R = + constructRationalFunction( + numerator - denominator * other, + denominator + ) + public override operator fun R.times(other: V): R = + constructRationalFunction( + numerator * other, + denominator + ) } \ No newline at end of file -- 2.34.1 From 5b8d6b601e54526c0148bd391e380d305ad4496a Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 22 Mar 2022 15:37:19 +0300 Subject: [PATCH 059/275] Added `degreeBy` to `Numbered...`. --- .../kscience/kmath/functions/NumberedPolynomial.kt | 12 ++++++++++++ .../kmath/functions/NumberedRationalFunction.kt | 8 ++++++++ 2 files changed, 20 insertions(+) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index 1f37a1c2b..570ccce8e 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -471,6 +471,18 @@ public open class NumberedPolynomialSpace>( } } } + /** + * Counts degree of the polynomial by the specified [variable]. + */ + public fun NumberedPolynomial.degreeBy(variable: Int): UInt = + coefficients.entries.maxOfOrNull { (degs, c) -> if (c.isZero()) 0u else degs.getOrElse(variable) { 0u } } ?: 0u + /** + * Counts degree of the polynomial by the specified [variables]. + */ + public fun NumberedPolynomial.degreeBy(variables: Collection): UInt = + coefficients.entries.maxOfOrNull { (degs, c) -> + if (c.isZero()) 0u else degs.withIndex().filter { (index, _) -> index in variables }.sumOf { it.value } + } ?: 0u /** * Count of variables occurring in the polynomial with positive power. If there is no such variable, * the result is `0`. diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt index b32f01f2a..2a4d942a6 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt @@ -126,6 +126,14 @@ public class NumberedRationalFunctionSpace> ( * 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`. -- 2.34.1 From d75a41482d09a7b97c049924df60b370ee14497c Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 22 Mar 2022 17:09:33 +0300 Subject: [PATCH 060/275] Added fabrics for `LabeledPolynomial` and `NumberedPolynomial`. --- .../kmath/functions/LabeledPolynomial.kt | 131 ++++++++------ .../kmath/functions/NumberedPolynomial.kt | 171 ++++++++---------- 2 files changed, 158 insertions(+), 144 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt index 29aeb6bb0..3d1b91f7b 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -54,59 +54,86 @@ internal constructor( */ internal fun Map.cleanUp() = filterValues { it > 0U } -//context(LabeledPolynomialSpace>) -//@Suppress("FunctionName") -//internal fun LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = false) : LabeledPolynomial { -// if (!toCheckInput) return LabeledPolynomial(coefs) -// -// val fixedCoefs = mutableMapOf, C>() -// -// for (entry in coefs) { -// val key = entry.key.cleanUp() -// val value = entry.value -// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value -// } -// -// return LabeledPolynomial( -// fixedCoefs.filterValues { it.isNotZero() } -// ) -//} -// -//context(LabeledPolynomialSpace>) -//@Suppress("FunctionName") -//internal fun LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = false) : LabeledPolynomial { -// if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) -// -// val fixedCoefs = mutableMapOf, C>() -// -// for (entry in pairs) { -// val key = entry.first.cleanUp() -// val value = entry.second -// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value -// } -// -// return LabeledPolynomial( -// fixedCoefs.filterValues { it.isNotZero() } -// ) -//} -// -//// TODO: Do not know how to make it without context receivers -//context(LabeledPolynomialSpace>) -//@Suppress("FunctionName") -//public fun LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) -// -//context(LabeledPolynomialSpace>) -//@Suppress("FunctionName") -//public fun LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) -// -//context(LabeledPolynomialSpace>) -//@Suppress("FunctionName") -//public fun LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(pairs.toList(), toCheckInput = true) -// -//context(LabeledPolynomialSpace>) -//public fun Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to constantOne)) +// Waiting for context receivers :( TODO: Replace with context receivers when they will be available -public fun C.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to this)) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(coefs, toCheckInput) +@Suppress("FunctionName") +internal fun > A.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial { + if (!toCheckInput) return LabeledPolynomial(coefs) + + val fixedCoefs = mutableMapOf, C>() + + for (entry in coefs) { + val key = entry.key.cleanUp() + val value = entry.value + fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value + } + + return LabeledPolynomial( + fixedCoefs.filterValues { it != zero } + ) +} + +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs, toCheckInput) +@Suppress("FunctionName") +internal fun > A.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial { + if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) + + val fixedCoefs = mutableMapOf, C>() + + for (entry in pairs) { + val key = entry.first.cleanUp() + val value = entry.second + fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value + } + + return LabeledPolynomial( + fixedCoefs.filterValues { it != zero } + ) +} + +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs = pairs, toCheckInput = toCheckInput) +@Suppress("FunctionName") +internal fun > A.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial { + if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) + + val fixedCoefs = mutableMapOf, C>() + + for (entry in pairs) { + val key = entry.first.cleanUp() + val value = entry.second + fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value + } + + return LabeledPolynomial( + fixedCoefs.filterValues { it != zero } + ) +} + +@Suppress("FunctionName") +public fun > A.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) +@Suppress("FunctionName") +public fun > LabeledPolynomialSpace.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) + +@Suppress("FunctionName") +public fun > A.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > LabeledPolynomialSpace.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) + +@Suppress("FunctionName") +public fun > A.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > LabeledPolynomialSpace.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) + +//context(A) +//public fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to one)) +//context(LabeledPolynomialSpace) +//public fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to constantOne)) + +public fun C.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to this)) /** * Space of polynomials. diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index 570ccce8e..411409e39 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -53,56 +53,86 @@ internal constructor( */ internal fun List.cleanUp() = subList(0, indexOfLast { it != 0U } + 1) -//context(NumberedPolynomialSpace>) -//@Suppress("FunctionName") -//internal fun NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = false) : NumberedPolynomial { -// if (!toCheckInput) return NumberedPolynomial(coefs) -// -// val fixedCoefs = mutableMapOf, C>() -// -// for (entry in coefs) { -// val key = entry.key.cleanUp() -// val value = entry.value -// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value -// } -// -// return NumberedPolynomial( -// fixedCoefs.filterValues { it.isNotZero() } -// ) -//} -// -//context(NumberedPolynomialSpace>) -//@Suppress("FunctionName") -//internal fun NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = false) : NumberedPolynomial { -// if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) -// -// val fixedCoefs = mutableMapOf, C>() -// -// for (entry in pairs) { -// val key = entry.first.cleanUp() -// val value = entry.second -// fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value -// } -// -// return NumberedPolynomial( -// fixedCoefs.filterValues { it.isNotZero() } -// ) -//} -// -//// TODO: Do not know how to make it without context receivers -//context(NumberedPolynomialSpace>) -//@Suppress("FunctionName") -//public fun NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) -// -//context(NumberedPolynomialSpace>) -//@Suppress("FunctionName") -//public fun NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) -// -//context(NumberedPolynomialSpace>) -//@Suppress("FunctionName") -//public fun NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(pairs.toList(), toCheckInput = true) +// Waiting for context receivers :( TODO: Replace with context receivers when they will be available -public fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(emptyList() to this)) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(coefs, toCheckInput) +@Suppress("FunctionName") +internal fun > A.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial { + if (!toCheckInput) return NumberedPolynomial(coefs) + + val fixedCoefs = mutableMapOf, C>() + + for (entry in coefs) { + val key = entry.key.cleanUp() + val value = entry.value + fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value + } + + return NumberedPolynomial( + fixedCoefs.filterValues { it != zero } + ) +} + +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs, toCheckInput) +@Suppress("FunctionName") +internal fun > A.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial { + if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) + + val fixedCoefs = mutableMapOf, C>() + + for (entry in pairs) { + val key = entry.first.cleanUp() + val value = entry.second + fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value + } + + return NumberedPolynomial( + fixedCoefs.filterValues { it != zero } + ) +} + +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs = pairs, toCheckInput = toCheckInput) +@Suppress("FunctionName") +internal fun > A.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial { + if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) + + val fixedCoefs = mutableMapOf, C>() + + for (entry in pairs) { + val key = entry.first.cleanUp() + val value = entry.second + fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value + } + + return NumberedPolynomial( + fixedCoefs.filterValues { it != zero } + ) +} + +@Suppress("FunctionName") +public fun > A.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) +@Suppress("FunctionName") +public fun > NumberedPolynomialSpace.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) + +@Suppress("FunctionName") +public fun > A.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > NumberedPolynomialSpace.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) + +@Suppress("FunctionName") +public fun > A.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > NumberedPolynomialSpace.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) + +//context(A) +//public fun > Symbol.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(mapOf(this to 1u) to one)) +//context(NumberedPolynomialSpace) +//public fun > Symbol.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(mapOf(this to 1u) to constantOne)) + +public fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(emptyList() to this)) /** * Space of polynomials. @@ -574,47 +604,4 @@ public open class NumberedPolynomialSpace>( for ((degs, c) in this) if (c.isZero()) this.remove(degs) } } - - @Suppress("FunctionName") - internal fun NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = false) : NumberedPolynomial { - if (!toCheckInput) return NumberedPolynomial(coefs) - - val fixedCoefs = mutableMapOf, C>() - - for (entry in coefs) { - val key = entry.key.cleanUp() - val value = entry.value - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return NumberedPolynomial( - fixedCoefs.filterValues { it.isNotZero() } - ) - } - - @Suppress("FunctionName") - internal fun NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = false) : NumberedPolynomial { - if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) - - val fixedCoefs = mutableMapOf, C>() - - for (entry in pairs) { - val key = entry.first.cleanUp() - val value = entry.second - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return NumberedPolynomial( - fixedCoefs.filterValues { it.isNotZero() } - ) - } - - @Suppress("FunctionName") - public fun NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) - - @Suppress("FunctionName") - public fun NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) - - @Suppress("FunctionName") - public fun NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(pairs.toList(), toCheckInput = true) } \ No newline at end of file -- 2.34.1 From 0a5122a974b1e6a6d888115e36bbe3118db931f3 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 22 Mar 2022 19:40:55 +0300 Subject: [PATCH 061/275] Prototyped DSL-like constructor for `NumberedPolynomial`. --- .../kmath/functions/NumberedPolynomial.kt | 58 ++++++++++++++++++- .../kmath/functions/labeledPolynomialUtil.kt | 47 --------------- .../kmath/functions/listPolynomialUtil.kt | 2 +- 3 files changed, 58 insertions(+), 49 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index 411409e39..80998d6bf 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.functions +import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.ScaleOperations import kotlin.contracts.InvocationKind @@ -132,7 +133,59 @@ public fun > NumberedPolynomialSpace.NumberedPolynomial(vara //context(NumberedPolynomialSpace) //public fun > Symbol.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(mapOf(this to 1u) to constantOne)) -public fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(emptyList() to this)) +//context(A) +//public fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(emptyList() to this)) + +@DslMarker +internal annotation class NumberedPolynomialConstructorDSL + +@NumberedPolynomialConstructorDSL +public class NumberedPolynomialTermSignatureBuilder { + private val signature: MutableList = ArrayList() + public fun build(): List = signature + public infix fun Int.inPowerOf(deg: UInt) { + if (this > signature.lastIndex) { + signature.addAll(List(this - signature.lastIndex - 1) { 0u }) + signature.add(deg) + } else { + signature[this] = deg + } + } + public infix fun Int.to(deg: UInt): Unit = this inPowerOf deg +} + +@NumberedPolynomialConstructorDSL +public class NumberedPolynomialBuilderOverRing internal constructor(internal val context: Ring, capacity: Int = 0) { + private val coefficients: MutableMap, C> = LinkedHashMap(capacity) + public fun build(): NumberedPolynomial = NumberedPolynomial(coefficients) + public operator fun C.invoke(block: NumberedPolynomialTermSignatureBuilder.() -> Unit) { + val signature = NumberedPolynomialTermSignatureBuilder().apply(block).build() + coefficients[signature] = context { coefficients.getOrElse(signature) { zero } + this@invoke } + } +} + +@NumberedPolynomialConstructorDSL +public class NumberedPolynomialBuilderOverPolynomialSpace internal constructor(internal val context: NumberedPolynomialSpace, capacity: Int = 0) { + private val coefficients: MutableMap, C> = LinkedHashMap(capacity) + public fun build(): NumberedPolynomial = NumberedPolynomial(coefficients) + public operator fun C.invoke(block: NumberedPolynomialTermSignatureBuilder.() -> Unit) { + val signature = NumberedPolynomialTermSignatureBuilder().apply(block).build() + coefficients[signature] = context { coefficients.getOrElse(signature) { constantZero } + this@invoke } + } +} + +@NumberedPolynomialConstructorDSL +@Suppress("FunctionName") +public fun > A.NumberedPolynomial(block: NumberedPolynomialBuilderOverRing.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilderOverRing(this).apply(block).build() +@NumberedPolynomialConstructorDSL +@Suppress("FunctionName") +public fun > A.NumberedPolynomial(capacity: Int, block: NumberedPolynomialBuilderOverRing.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilderOverRing(this, capacity).apply(block).build() +@NumberedPolynomialConstructorDSL +@Suppress("FunctionName") +public fun > NumberedPolynomialSpace.NumberedPolynomial(block: NumberedPolynomialBuilderOverPolynomialSpace.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilderOverPolynomialSpace(this).apply(block).build() +@NumberedPolynomialConstructorDSL +@Suppress("FunctionName") +public fun > NumberedPolynomialSpace.NumberedPolynomial(capacity: Int, block: NumberedPolynomialBuilderOverPolynomialSpace.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilderOverPolynomialSpace(this, capacity).apply(block).build() /** * Space of polynomials. @@ -604,4 +657,7 @@ public open class NumberedPolynomialSpace>( for ((degs, c) in this) if (c.isZero()) this.remove(degs) } } + + // TODO: Move to other constructors with context receiver + public fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(emptyList() to this)) } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt index 27fdd7d7b..88d357413 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt @@ -17,53 +17,6 @@ import kotlin.contracts.contract // TODO: Docs -//// TODO: Reuse underlying ring extensions -// -//context(LabeledPolynomialSpace) -//@Suppress("NOTHING_TO_INLINE") -//fun > numberConstant(value: Int): C = ring { number(value) } -// -//context(LabeledPolynomialSpace) -//fun > power(arg: C, pow: UInt): C = ring { power(arg, pow) } -// -//context(LabeledPolynomialSpace) -//fun > multiplyWithPower(base: C, arg: C, pow: UInt): C = ring { multiplyWithPower(base, arg, pow) } -// - -// -//context(LabeledPolynomialSpace) -//fun > power(arg: Symbol, pow: UInt): LabeledPolynomial = -// if (pow == 0U) one -// else LabeledPolynomial(mapOf( -// mapOf(arg to pow) to constantOne -// )) -// - -// -//context(LabeledPolynomialSpace) -//fun > number(value: Int): LabeledPolynomial = ring { LabeledPolynomial(mapOf(emptyMap() to number(value))) } -// -//context(LabeledPolynomialSpace) -//fun > multiplyWithPower(base: LabeledPolynomial, arg: LabeledPolynomial, pow: UInt): LabeledPolynomial = -// when { -// arg.isZero() && pow > 0U -> base -// arg.isOne() -> base -// arg.isMinusOne() -> if (pow % 2U == 0U) base else -base -// else -> multiplyWithPowerInternalLogic(base, arg, pow) -// } -// -//// Trivial but very slow -//context(LabeledPolynomialSpace) -//internal tailrec fun > multiplyWithPowerInternalLogic(base: LabeledPolynomial, arg: LabeledPolynomial, exponent: UInt): LabeledPolynomial = -// when { -// exponent == 0U -> base -// exponent == 1U -> base * arg -// exponent % 2U == 0U -> multiplyWithPowerInternalLogic(base, arg * arg, exponent / 2U) -// exponent % 2U == 1U -> multiplyWithPowerInternalLogic(base * arg, arg * arg, exponent / 2U) -// else -> error("Error in raising ring instant by unsigned integer: got reminder by division by 2 different from 0 and 1") -// } -// - /** * Creates a [LabeledPolynomialSpace] over a received ring. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt index df5ba593a..35155d09d 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt @@ -124,7 +124,7 @@ public fun ListPolynomial.substitute(ring: Ring, arg: ListPolynomial = MutableList(thisDegree * argDegree + 1) { constantZero } resultCoefs[0] = coefficients[thisDegree] -- 2.34.1 From 420bf05b22fa107ad33cf2bb5b05795c8b22b96e Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 22 Mar 2022 19:42:59 +0300 Subject: [PATCH 062/275] Fixed annoying JVM clashes :expressionless: --- .../kscience/kmath/functions/Polynomial.kt | 24 ++++++++ .../kmath/functions/RationalFunction.kt | 61 +++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 224e18832..d44c47dd6 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -416,35 +416,59 @@ public interface PolynomialSpaceOverRing, A: Ring> : Poly public override val constantOne: C get() = ring.one } +@Suppress("INAPPLICABLE_JVM_NAME") public interface MultivariatePolynomialSpace>: PolynomialSpace { + @JvmName("VariableIntPlus") public operator fun V.plus(other: Int): P + @JvmName("VariableIntMinus") public operator fun V.minus(other: Int): P + @JvmName("VariableIntMinusTimes") public operator fun V.times(other: Int): P + @JvmName("IntVariablePlus") public operator fun Int.plus(other: V): P + @JvmName("IntVariableMinus") public operator fun Int.minus(other: V): P + @JvmName("IntVariableTimes") public operator fun Int.times(other: V): P + @JvmName("ConstantVariablePlus") public operator fun C.plus(other: V): P + @JvmName("ConstantVariableMinus") public operator fun C.minus(other: V): P + @JvmName("ConstantVariableTimes") public operator fun C.times(other: V): P + @JvmName("VariableConstantPlus") public operator fun V.plus(other: C): P + @JvmName("VariableConstantMinus") public operator fun V.minus(other: C): P + @JvmName("VariableConstantTimes") public operator fun V.times(other: C): P + @JvmName("VariableUnaryPlus") public operator fun V.unaryPlus(): P + @JvmName("VariableUnaryMinus") public operator fun V.unaryMinus(): P + @JvmName("VariablePlus") public operator fun V.plus(other: V): P + @JvmName("VariableMinus") public operator fun V.minus(other: V): P + @JvmName("VariableTimes") public operator fun V.times(other: V): P + @JvmName("VariablePolynomialPlus") public operator fun V.plus(other: P): P + @JvmName("VariablePolynomialMinus") public operator fun V.minus(other: P): P + @JvmName("VariablePolynomialTimes") public operator fun V.times(other: P): P + @JvmName("PolynomialVariablePlus") public operator fun P.plus(other: V): P + @JvmName("PolynomialVariableMinus") public operator fun P.minus(other: V): P + @JvmName("PolynomialVariableTimes") public operator fun P.times(other: V): P /** diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index c5fcde8ed..9c0263c4c 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -1308,48 +1308,78 @@ public abstract class PolynomialSpaceOfFractions< public override val one: R get() = constructRationalFunction(polynomialOne) } +@Suppress("INAPPLICABLE_JVM_NAME") public interface MultivariateRationalFunctionalSpace< C, V, P: Polynomial, R: RationalFunction >: RationalFunctionalSpace { + @JvmName("VariableIntPlus") public operator fun V.plus(other: Int): P + @JvmName("VariableIntMinus") public operator fun V.minus(other: Int): P + @JvmName("VariableIntMinusTimes") public operator fun V.times(other: Int): P + @JvmName("IntVariablePlus") public operator fun Int.plus(other: V): P + @JvmName("IntVariableMinus") public operator fun Int.minus(other: V): P + @JvmName("IntVariableTimes") public operator fun Int.times(other: V): P + @JvmName("ConstantVariablePlus") public operator fun C.plus(other: V): P + @JvmName("ConstantVariableMinus") public operator fun C.minus(other: V): P + @JvmName("ConstantVariableTimes") public operator fun C.times(other: V): P + @JvmName("VariableConstantPlus") public operator fun V.plus(other: C): P + @JvmName("VariableConstantMinus") public operator fun V.minus(other: C): P + @JvmName("VariableConstantTimes") public operator fun V.times(other: C): P + @JvmName("VariableUnaryPlus") public operator fun V.unaryPlus(): P + @JvmName("VariableUnaryMinus") public operator fun V.unaryMinus(): P + @JvmName("VariablePlus") public operator fun V.plus(other: V): P + @JvmName("VariableMinus") public operator fun V.minus(other: V): P + @JvmName("VariableTimes") public operator fun V.times(other: V): P + @JvmName("VariablePolynomialPlus") public operator fun V.plus(other: P): P + @JvmName("VariablePolynomialMinus") public operator fun V.minus(other: P): P + @JvmName("VariablePolynomialTimes") public operator fun V.times(other: P): P + @JvmName("PolynomialVariablePlus") public operator fun P.plus(other: V): P + @JvmName("PolynomialVariableMinus") public operator fun P.minus(other: V): P + @JvmName("PolynomialVariableTimes") public operator fun P.times(other: V): P + @JvmName("VariableRationalFunctionPlus") public operator fun V.plus(other: R): R + @JvmName("VariableRationalFunctionMinus") public operator fun V.minus(other: R): R + @JvmName("VariableRationalFunctionTimes") public operator fun V.times(other: R): R + @JvmName("RationalFunctionVariablePlus") public operator fun R.plus(other: V): R + @JvmName("RationalFunctionVariableMinus") public operator fun R.minus(other: V): R + @JvmName("RationalFunctionVariableTimes") public operator fun R.times(other: V): R /** @@ -1403,6 +1433,7 @@ public interface MultivariateRationalFunctionalSpaceOverPolynomialSpace< AP: PolynomialSpace, > : RationalFunctionalSpaceOverPolynomialSpace, MultivariateRationalFunctionalSpace +@Suppress("INAPPLICABLE_JVM_NAME") public interface MultivariateRationalFunctionalSpaceOverMultivariatePolynomialSpace< C, V, @@ -1410,34 +1441,57 @@ public interface MultivariateRationalFunctionalSpaceOverMultivariatePolynomialSp R: RationalFunction, AP: MultivariatePolynomialSpace, > : MultivariateRationalFunctionalSpaceOverPolynomialSpace { + @JvmName("VariableIntPlus") public override operator fun V.plus(other: Int): P = polynomialRing { this@plus + other } + @JvmName("VariableIntMinus") public override operator fun V.minus(other: Int): P = polynomialRing { this@minus - other } + @JvmName("VariableIntMinusTimes") public override operator fun V.times(other: Int): P = polynomialRing { this@times * other } + @JvmName("IntVariablePlus") public override operator fun Int.plus(other: V): P = polynomialRing { this@plus + other } + @JvmName("IntVariableMinus") public override operator fun Int.minus(other: V): P = polynomialRing { this@minus - other } + @JvmName("IntVariableTimes") public override operator fun Int.times(other: V): P = polynomialRing { this@times * other } + @JvmName("ConstantVariablePlus") public override operator fun C.plus(other: V): P = polynomialRing { this@plus + other } + @JvmName("ConstantVariableMinus") public override operator fun C.minus(other: V): P = polynomialRing { this@minus - other } + @JvmName("ConstantVariableTimes") public override operator fun C.times(other: V): P = polynomialRing { this@times * other } + @JvmName("VariableConstantPlus") public override operator fun V.plus(other: C): P = polynomialRing { this@plus + other } + @JvmName("VariableConstantMinus") public override operator fun V.minus(other: C): P = polynomialRing { this@minus - other } + @JvmName("VariableConstantTimes") public override operator fun V.times(other: C): P = polynomialRing { this@times * other } + @JvmName("VariableUnaryPlus") public override operator fun V.unaryPlus(): P = polynomialRing { +this@unaryPlus } + @JvmName("VariableUnaryMinus") public override operator fun V.unaryMinus(): P = polynomialRing { -this@unaryMinus } + @JvmName("VariablePlus") public override operator fun V.plus(other: V): P = polynomialRing { this@plus + other } + @JvmName("VariableMinus") public override operator fun V.minus(other: V): P = polynomialRing { this@minus - other } + @JvmName("VariableTimes") public override operator fun V.times(other: V): P = polynomialRing { this@times * other } + @JvmName("VariablePolynomialPlus") public override operator fun V.plus(other: P): P = polynomialRing { this@plus + other } + @JvmName("VariablePolynomialMinus") public override operator fun V.minus(other: P): P = polynomialRing { this@minus - other } + @JvmName("VariablePolynomialTimes") public override operator fun V.times(other: P): P = polynomialRing { this@times * other } + @JvmName("PolynomialVariablePlus") public override operator fun P.plus(other: V): P = polynomialRing { this@plus + other } + @JvmName("PolynomialVariableMinus") public override operator fun P.minus(other: V): P = polynomialRing { this@minus - other } + @JvmName("PolynomialVariableTimes") public override operator fun P.times(other: V): P = polynomialRing { this@times * other } /** @@ -1466,38 +1520,45 @@ public interface MultivariateRationalFunctionalSpaceOverMultivariatePolynomialSp public override val P.countOfVariables: Int get() = polynomialRing { countOfVariables } } +@Suppress("INAPPLICABLE_JVM_NAME") public abstract class MultivariatePolynomialSpaceOfFractions< C, V, P: Polynomial, R: RationalFunction, > : MultivariateRationalFunctionalSpace, PolynomialSpaceOfFractions() { + @JvmName("VariableRationalFunctionPlus") public override operator fun V.plus(other: R): R = constructRationalFunction( this * other.denominator + other.numerator, other.denominator ) + @JvmName("VariableRationalFunctionMinus") public override operator fun V.minus(other: R): R = constructRationalFunction( this * other.denominator - other.numerator, other.denominator ) + @JvmName("VariableRationalFunctionTimes") public override operator fun V.times(other: R): R = constructRationalFunction( this * other.numerator, other.denominator ) + @JvmName("RationalFunctionVariablePlus") public override operator fun R.plus(other: V): R = constructRationalFunction( numerator + denominator * other, denominator ) + @JvmName("RationalFunctionVariableMinus") public override operator fun R.minus(other: V): R = constructRationalFunction( numerator - denominator * other, denominator ) + @JvmName("RationalFunctionVariableTimes") public override operator fun R.times(other: V): R = constructRationalFunction( numerator * other, -- 2.34.1 From 060f0ee35dfdfe510b70c55550a379f47d6106d7 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Fri, 25 Mar 2022 00:57:32 +0300 Subject: [PATCH 063/275] Removed comparability feature. --- .../kmath/functions/LabeledPolynomial.kt | 286 +++++------------ .../functions/LabeledRationalFunction.kt | 58 +--- .../kmath/functions/ListPolynomial.kt | 203 +++--------- .../kmath/functions/ListRationalFunction.kt | 16 +- .../kmath/functions/NumberedPolynomial.kt | 246 ++++----------- .../functions/NumberedRationalFunction.kt | 60 +--- .../kscience/kmath/functions/Polynomial.kt | 86 ----- .../kmath/functions/RationalFunction.kt | 297 ++---------------- .../kmath/functions/listPolynomialUtil.kt | 9 +- .../functions/listRationalFunctionUtil.kt | 6 +- .../kmath/functions/ListPolynomialTest.kt | 156 +-------- .../kmath/functions/ListPolynomialUtilTest.kt | 2 +- 12 files changed, 242 insertions(+), 1183 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt index 3d1b91f7b..908e89534 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -58,6 +58,8 @@ internal fun Map.cleanUp() = filterValues { it > 0U } @Suppress("FunctionName", "NOTHING_TO_INLINE") internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(coefs, toCheckInput) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(coefs, toCheckInput) @Suppress("FunctionName") internal fun > A.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial { if (!toCheckInput) return LabeledPolynomial(coefs) @@ -70,13 +72,13 @@ internal fun > A.LabeledPolynomial(coefs: Map, C fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value } - return LabeledPolynomial( - fixedCoefs.filterValues { it != zero } - ) + return LabeledPolynomial(fixedCoefs) } @Suppress("FunctionName", "NOTHING_TO_INLINE") internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs, toCheckInput) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs, toCheckInput) @Suppress("FunctionName") internal fun > A.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial { if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) @@ -89,13 +91,13 @@ internal fun > A.LabeledPolynomial(pairs: Collection( - fixedCoefs.filterValues { it != zero } - ) + return LabeledPolynomial(fixedCoefs) } @Suppress("FunctionName", "NOTHING_TO_INLINE") internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs = pairs, toCheckInput = toCheckInput) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs = pairs, toCheckInput = toCheckInput) @Suppress("FunctionName") internal fun > A.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial { if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) @@ -108,25 +110,29 @@ internal fun > A.LabeledPolynomial(vararg pairs: Pair( - fixedCoefs.filterValues { it != zero } - ) + return LabeledPolynomial(fixedCoefs) } @Suppress("FunctionName") public fun > A.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) @Suppress("FunctionName") public fun > LabeledPolynomialSpace.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) +@Suppress("FunctionName") +public fun > LabeledRationalFunctionSpace.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) @Suppress("FunctionName") public fun > A.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) @Suppress("FunctionName") public fun > LabeledPolynomialSpace.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > LabeledRationalFunctionSpace.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) @Suppress("FunctionName") public fun > A.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) @Suppress("FunctionName") public fun > LabeledPolynomialSpace.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > LabeledRationalFunctionSpace.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) //context(A) //public fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to one)) @@ -196,19 +202,17 @@ public class LabeledPolynomialSpace>( */ public override operator fun LabeledPolynomial.plus(other: Int): LabeledPolynomial = if (other == 0) this - else - LabeledPolynomial( - coefficients - .toMutableMap() + else with(coefficients) { + if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to other.asConstant())) + else LabeledPolynomial( + toMutableMap() .apply { val degs = emptyMap() - val result = getOrElse(degs) { constantZero } + other - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = getOrElse(degs) { constantZero } + other } ) + } /** * Returns difference between the polynomial and the integer represented as polynomial. * @@ -216,19 +220,17 @@ public class LabeledPolynomialSpace>( */ public override operator fun LabeledPolynomial.minus(other: Int): LabeledPolynomial = if (other == 0) this - else - LabeledPolynomial( - coefficients - .toMutableMap() + else with(coefficients) { + if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to (-other).asConstant())) + else LabeledPolynomial( + toMutableMap() .apply { val degs = emptyMap() - val result = getOrElse(degs) { constantZero } - other - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = getOrElse(degs) { constantZero } - other } ) + } /** * Returns product of the polynomial and the integer represented as polynomial. * @@ -238,7 +240,8 @@ public class LabeledPolynomialSpace>( if (other == 0) zero else LabeledPolynomial( coefficients - .applyAndRemoveZeros { + .toMutableMap() + .apply { for (degs in keys) this[degs] = this[degs]!! * other } ) @@ -250,19 +253,17 @@ public class LabeledPolynomialSpace>( */ public override operator fun Int.plus(other: LabeledPolynomial): LabeledPolynomial = if (this == 0) other - else - LabeledPolynomial( - other.coefficients - .toMutableMap() + else with(other.coefficients) { + if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@plus.asConstant())) + else LabeledPolynomial( + toMutableMap() .apply { val degs = emptyMap() - val result = this@plus + getOrElse(degs) { constantZero } - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = this@plus + getOrElse(degs) { constantZero } } ) + } /** * Returns difference between the integer represented as polynomial and the polynomial. * @@ -270,19 +271,17 @@ public class LabeledPolynomialSpace>( */ public override operator fun Int.minus(other: LabeledPolynomial): LabeledPolynomial = if (this == 0) other - else - LabeledPolynomial( - other.coefficients - .toMutableMap() + else with(other.coefficients) { + if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@minus.asConstant())) + else LabeledPolynomial( + toMutableMap() .apply { val degs = emptyMap() - val result = this@minus - getOrElse(degs) { constantZero } - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = this@minus - getOrElse(degs) { constantZero } } ) + } /** * Returns product of the integer represented as polynomial and the polynomial. * @@ -292,7 +291,8 @@ public class LabeledPolynomialSpace>( if (this == 0) zero else LabeledPolynomial( other.coefficients - .applyAndRemoveZeros { + .toMutableMap() + .apply { for (degs in keys) this[degs] = this@times * this[degs]!! } ) @@ -303,46 +303,32 @@ public class LabeledPolynomialSpace>( public override fun number(value: Int): LabeledPolynomial = number(constantNumber(value)) public override operator fun C.plus(other: Symbol): LabeledPolynomial = - if (isZero()) LabeledPolynomial(mapOf( - mapOf(other to 1U) to constantOne, - )) - else LabeledPolynomial(mapOf( + LabeledPolynomial(mapOf( mapOf(other to 1U) to constantOne, emptyMap() to this@plus, )) public override operator fun C.minus(other: Symbol): LabeledPolynomial = - if (isZero()) LabeledPolynomial(mapOf( - mapOf(other to 1U) to -constantOne, - )) - else LabeledPolynomial(mapOf( + LabeledPolynomial(mapOf( mapOf(other to 1U) to -constantOne, emptyMap() to this@minus, )) public override operator fun C.times(other: Symbol): LabeledPolynomial = - if (isZero()) zero - else LabeledPolynomial(mapOf( + LabeledPolynomial(mapOf( mapOf(other to 1U) to this@times, )) public override operator fun Symbol.plus(other: C): LabeledPolynomial = - if (other.isZero()) LabeledPolynomial(mapOf( - mapOf(this@plus to 1U) to constantOne, - )) - else LabeledPolynomial(mapOf( + LabeledPolynomial(mapOf( mapOf(this@plus to 1U) to constantOne, emptyMap() to other, )) public override operator fun Symbol.minus(other: C): LabeledPolynomial = - if (other.isZero()) LabeledPolynomial(mapOf( - mapOf(this@minus to 1U) to -constantOne, - )) - else LabeledPolynomial(mapOf( + LabeledPolynomial(mapOf( mapOf(this@minus to 1U) to -constantOne, emptyMap() to other, )) public override operator fun Symbol.times(other: C): LabeledPolynomial = - if (other.isZero()) zero - else LabeledPolynomial(mapOf( + LabeledPolynomial(mapOf( mapOf(this@times to 1U) to other, )) @@ -350,18 +336,14 @@ public class LabeledPolynomialSpace>( * Returns sum of the constant represented as polynomial and the polynomial. */ override operator fun C.plus(other: LabeledPolynomial): LabeledPolynomial = - if (this.isZero()) other - else with(other.coefficients) { + with(other.coefficients) { if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@plus)) else LabeledPolynomial( toMutableMap() .apply { val degs = emptyMap() - val result = this@plus + getOrElse(degs) { constantZero } - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = this@plus + getOrElse(degs) { constantZero } } ) } @@ -369,8 +351,7 @@ public class LabeledPolynomialSpace>( * Returns difference between the constant represented as polynomial and the polynomial. */ override operator fun C.minus(other: LabeledPolynomial): LabeledPolynomial = - if (this.isZero()) other - else with(other.coefficients) { + with(other.coefficients) { if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@minus)) else LabeledPolynomial( toMutableMap() @@ -379,10 +360,7 @@ public class LabeledPolynomialSpace>( val degs = emptyMap() - val result = this@minus - getOrElse(degs) { constantZero } - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = this@minus - getOrElse(degs) { constantZero } } ) } @@ -390,10 +368,10 @@ public class LabeledPolynomialSpace>( * Returns product of the constant represented as polynomial and the polynomial. */ override operator fun C.times(other: LabeledPolynomial): LabeledPolynomial = - if (this.isZero()) zero - else LabeledPolynomial( + LabeledPolynomial( other.coefficients - .applyAndRemoveZeros { + .toMutableMap() + .apply { for (degs in keys) this[degs] = this@times * this[degs]!! } ) @@ -402,18 +380,14 @@ public class LabeledPolynomialSpace>( * Returns sum of the constant represented as polynomial and the polynomial. */ override operator fun LabeledPolynomial.plus(other: C): LabeledPolynomial = - if (other.isZero()) this - else with(coefficients) { + with(coefficients) { if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to other)) else LabeledPolynomial( toMutableMap() .apply { val degs = emptyMap() - val result = getOrElse(degs) { constantZero } + other - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = getOrElse(degs) { constantZero } + other } ) } @@ -421,8 +395,7 @@ public class LabeledPolynomialSpace>( * Returns difference between the constant represented as polynomial and the polynomial. */ override operator fun LabeledPolynomial.minus(other: C): LabeledPolynomial = - if (other.isZero()) this - else with(coefficients) { + with(coefficients) { if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to other)) else LabeledPolynomial( toMutableMap() @@ -431,10 +404,7 @@ public class LabeledPolynomialSpace>( val degs = emptyMap() - val result = getOrElse(degs) { constantZero } - other - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = getOrElse(degs) { constantZero } - other } ) } @@ -442,10 +412,10 @@ public class LabeledPolynomialSpace>( * Returns product of the constant represented as polynomial and the polynomial. */ override operator fun LabeledPolynomial.times(other: C): LabeledPolynomial = - if (other.isZero()) zero - else LabeledPolynomial( + LabeledPolynomial( coefficients - .applyAndRemoveZeros { + .toMutableMap() + .apply { for (degs in keys) this[degs] = this[degs]!! * other } ) @@ -454,8 +424,7 @@ public class LabeledPolynomialSpace>( * Converts the constant [value] to polynomial. */ public override fun number(value: C): LabeledPolynomial = - if (value == 0) zero - else LabeledPolynomial(mapOf(emptyMap() to value)) + LabeledPolynomial(mapOf(emptyMap() to value)) public override operator fun Symbol.unaryPlus(): LabeledPolynomial = LabeledPolynomial(mapOf( @@ -495,10 +464,7 @@ public class LabeledPolynomialSpace>( .apply { val degs = mapOf(this@plus to 1U) - val result = constantOne + getOrElse(degs) { constantZero } - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = constantOne + getOrElse(degs) { constantZero } } ) } @@ -512,10 +478,7 @@ public class LabeledPolynomialSpace>( val degs = mapOf(this@minus to 1U) - val result = constantOne - getOrElse(degs) { constantZero } - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = constantOne - getOrElse(degs) { constantZero } } ) } @@ -533,10 +496,7 @@ public class LabeledPolynomialSpace>( .apply { val degs = mapOf(other to 1U) - val result = constantOne + getOrElse(degs) { constantZero } - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = constantOne + getOrElse(degs) { constantZero } } ) } @@ -548,10 +508,7 @@ public class LabeledPolynomialSpace>( .apply { val degs = mapOf(other to 1U) - val result = constantOne - getOrElse(degs) { constantZero } - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = constantOne - getOrElse(degs) { constantZero } } ) } @@ -573,7 +530,7 @@ public class LabeledPolynomialSpace>( */ override operator fun LabeledPolynomial.plus(other: LabeledPolynomial): LabeledPolynomial = LabeledPolynomial( - buildCoefficients(coefficients.size + other.coefficients.size) { + buildMap(coefficients.size + other.coefficients.size) { other.coefficients.mapValuesTo(this) { it.value } other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value } } @@ -583,7 +540,7 @@ public class LabeledPolynomialSpace>( */ override operator fun LabeledPolynomial.minus(other: LabeledPolynomial): LabeledPolynomial = LabeledPolynomial( - buildCoefficients(coefficients.size + other.coefficients.size) { + buildMap(coefficients.size + other.coefficients.size) { other.coefficients.mapValuesTo(this) { it.value } other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value } } @@ -592,20 +549,16 @@ public class LabeledPolynomialSpace>( * Returns product of the polynomials. */ override operator fun LabeledPolynomial.times(other: LabeledPolynomial): LabeledPolynomial = - when { - isZero() -> zero - other.isZero() -> zero - else -> LabeledPolynomial( - buildCoefficients(coefficients.size * other.coefficients.size) { - for ((degs1, c1) in coefficients) for ((degs2, c2) in other.coefficients) { - val degs = degs1.toMutableMap() - degs2.mapValuesTo(degs) { (variable, deg) -> degs.getOrElse(variable) { 0u } + deg } - val c = c1 * c2 - this[degs] = if (degs in this) this[degs]!! + c else c - } + LabeledPolynomial( + buildMap(coefficients.size * other.coefficients.size) { + for ((degs1, c1) in coefficients) for ((degs2, c2) in other.coefficients) { + val degs = degs1.toMutableMap() + degs2.mapValuesTo(degs) { (variable, deg) -> degs.getOrElse(variable) { 0u } + deg } + val c = c1 * c2 + this[degs] = if (degs in this) this[degs]!! + c else c } - ) - } + } + ) /** * Instance of zero polynomial (zero of the polynomial ring). @@ -616,22 +569,12 @@ public class LabeledPolynomialSpace>( */ override val one: LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to constantOne)) - /** - * Checks equality of the polynomials. - */ - override infix fun LabeledPolynomial.equalsTo(other: LabeledPolynomial): Boolean = - when { - this === other -> true - else -> coefficients.size == other.coefficients.size && - coefficients.all { (key, value) -> with(other.coefficients) { key in this && this[key] == value } } - } - /** * 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, c) -> if (c.isZero()) -1 else degs.values.sum().toInt() } ?: -1 + get() = coefficients.entries.maxOfOrNull { (degs, c) -> 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. @@ -642,8 +585,8 @@ public class LabeledPolynomialSpace>( public override val LabeledPolynomial.degrees: Map get() = buildMap { - coefficients.entries.forEach { (degs, c) -> - if (c.isNotZero()) degs.mapValuesTo(this) { (variable, deg) -> + coefficients.entries.forEach { (degs, _) -> + degs.mapValuesTo(this) { (variable, deg) -> max(getOrElse(variable) { 0u }, deg) } } @@ -652,55 +595,25 @@ public class LabeledPolynomialSpace>( * Counts degree of the polynomial by the specified [variable]. */ public override fun LabeledPolynomial.degreeBy(variable: Symbol): UInt = - coefficients.entries.maxOfOrNull { (degs, c) -> if (c.isZero()) 0u else degs.getOrElse(variable) { 0u } } ?: 0u + 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, c) -> if (c.isZero()) 0u else degs.filterKeys { it in variables }.values.sum() } ?: 0u + 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, c) -> if (c.isNotZero()) addAll(degs.keys) } + 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 - /** - * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. - */ - override fun LabeledPolynomial.isConstant(): Boolean = - coefficients.all { (degs, c) -> degs.isEmpty() || c.isZero() } - /** - * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. - */ - override fun LabeledPolynomial.isNonZeroConstant(): Boolean = - with(coefficients) { - var foundAbsoluteTermAndItIsNotZero = false - for ((degs, c) in this) { - if (degs.isNotEmpty()) if (c.isNotZero()) return@with false - else { - if (c.isZero()) return@with false - else foundAbsoluteTermAndItIsNotZero = true - } - } - foundAbsoluteTermAndItIsNotZero - } - /** - * If polynomial is a constant polynomial represents and returns it as constant. - * Otherwise, (when the polynomial is not constant polynomial) returns `null`. - */ - override fun LabeledPolynomial.asConstantOrNull(): C? = - with(coefficients) { - if(isConstant()) getOrElse(emptyMap()) { constantZero } - else null - } - // @Suppress("NOTHING_TO_INLINE") // public inline fun LabeledPolynomial.substitute(argument: Map): LabeledPolynomial = this.substitute(ring, argument) // @Suppress("NOTHING_TO_INLINE") @@ -719,33 +632,4 @@ public class LabeledPolynomialSpace>( // @Suppress("NOTHING_TO_INLINE") // @JvmName("invokePolynomial") // public inline operator fun LabeledPolynomial.invoke(argument: Map>): LabeledPolynomial = this.substitute(ring, argument) - - // TODO: Move to other internal utilities with context receiver - @JvmName("applyAndRemoveZerosInternal") - internal fun MutableMap, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : MutableMap, C> { - contract { - callsInPlace(block, InvocationKind.EXACTLY_ONCE) - } - block() - for ((degs, c) in this) if (c.isZero()) this.remove(degs) - return this - } - internal fun Map, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : Map, C> = - toMutableMap().applyAndRemoveZeros(block) - @OptIn(ExperimentalTypeInference::class) - internal inline fun buildCoefficients(@BuilderInference builderAction: MutableMap, C>.() -> Unit): Map, C> { - contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } - return buildMap { - builderAction() - for ((degs, c) in this) if (c.isZero()) this.remove(degs) - } - } - @OptIn(ExperimentalTypeInference::class) - internal inline fun buildCoefficients(capacity: Int, @BuilderInference builderAction: MutableMap, C>.() -> Unit): Map, C> { - contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } - return buildMap(capacity) { - builderAction() - for ((degs, c) in this) if (c.isZero()) this.remove(degs) - } - } } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt index 00dd3bb47..0f46520dc 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt @@ -19,45 +19,35 @@ public class LabeledRationalFunction( // Waiting for context receivers :( TODO: Replace with context receivers when they will be available -@Suppress("FunctionName") -internal fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numerator: LabeledPolynomial, denominator: LabeledPolynomial): LabeledRationalFunction = - if (denominator.isZero()) throw ArithmeticException("/ by zero") - else LabeledRationalFunction(numerator, denominator) -@Suppress("FunctionName") -internal fun > A.LabeledRationalFunction(numerator: LabeledPolynomial, denominator: LabeledPolynomial): LabeledRationalFunction = - if (denominator.coefficients.values.all { it == zero }) throw ArithmeticException("/ by zero") - else LabeledRationalFunction(numerator, denominator) @Suppress("FunctionName") public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): LabeledRationalFunction = - if (denominatorCoefficients.values.all { it == zero }) throw ArithmeticException("/ by zero") - else LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients), - LabeledPolynomial(denominatorCoefficients) + LabeledRationalFunction( + LabeledPolynomial(numeratorCoefficients, toCheckInput = true), + LabeledPolynomial(denominatorCoefficients, toCheckInput = true) ) @Suppress("FunctionName") public fun > A.LabeledRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): LabeledRationalFunction = - if (denominatorCoefficients.values.all { it == zero }) throw ArithmeticException("/ by zero") - else LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients), - LabeledPolynomial(denominatorCoefficients) + LabeledRationalFunction( + LabeledPolynomial(numeratorCoefficients, toCheckInput = true), + LabeledPolynomial(denominatorCoefficients, toCheckInput = true) ) @Suppress("FunctionName") public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numerator: LabeledPolynomial): LabeledRationalFunction = LabeledRationalFunction(numerator, polynomialOne) @Suppress("FunctionName") public fun > A.LabeledRationalFunction(numerator: LabeledPolynomial): LabeledRationalFunction = - LabeledRationalFunction(numerator, LabeledPolynomial(mapOf(emptyMap() to one))) + LabeledRationalFunction(numerator, LabeledPolynomial(mapOf(emptyMap() to one), toCheckInput = false)) @Suppress("FunctionName") public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numeratorCoefficients: Map, C>): LabeledRationalFunction = LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients), + LabeledPolynomial(numeratorCoefficients, toCheckInput = true), polynomialOne ) @Suppress("FunctionName") public fun > A.LabeledRationalFunction(numeratorCoefficients: Map, C>): LabeledRationalFunction = LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients), - LabeledPolynomial(mapOf(emptyMap() to one)) + LabeledPolynomial(numeratorCoefficients, toCheckInput = true), + LabeledPolynomial(mapOf(emptyMap() to one), toCheckInput = false) ) public class LabeledRationalFunctionSpace>( @@ -82,38 +72,16 @@ public class LabeledRationalFunctionSpace>( numerator: LabeledPolynomial, denominator: LabeledPolynomial ): LabeledRationalFunction = - LabeledRationalFunction(numerator, denominator) + LabeledRationalFunction(numerator, denominator) /** * Instance of zero rational function (zero of the rational functions ring). */ - public override val zero: LabeledRationalFunction = LabeledRationalFunction(polynomialZero, polynomialOne) + public override val zero: LabeledRationalFunction = LabeledRationalFunction(polynomialZero, polynomialOne) /** * Instance of unit polynomial (unit of the rational functions ring). */ - public override val one: LabeledRationalFunction = LabeledRationalFunction(polynomialOne, polynomialOne) - - /** - * Checks equality of the rational functions. - */ - public override infix fun LabeledRationalFunction.equalsTo(other: LabeledRationalFunction): Boolean { - if (this === other) return true - - if (numerator.isZero() != other.numerator.isZero()) return false - - val variables = this.variables union other.variables - val thisNumeratorDegrees = this.numerator.degrees - val thisDenominatorDegrees = this.denominator.degrees - val otherNumeratorDegrees = other.numerator.degrees - val otherDenominatorDegrees = other.denominator.degrees - for (variable in variables) - if ( - thisNumeratorDegrees.getOrElse(variable) { 0u } + otherDenominatorDegrees.getOrElse(variable) { 0u } - != thisDenominatorDegrees.getOrElse(variable) { 0u } + otherNumeratorDegrees.getOrElse(variable) { 0u } - ) return false - - return numerator * other.denominator equalsTo other.numerator * denominator - } + public override val one: LabeledRationalFunction = LabeledRationalFunction(polynomialOne, polynomialOne) // TODO: Разобрать diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt index 90e9cde69..711d2bb49 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt @@ -91,13 +91,9 @@ public open class ListPolynomialSpace>( .toMutableList() .apply { val result = getOrElse(0) { constantZero } + other - val isResultZero = result.isZero() - when { - size == 0 && !isResultZero -> add(result) - size > 1 || !isResultZero -> this[0] = result - else -> clear() - } + if(size == 0) add(result) + else this[0] = result } ) /** @@ -113,13 +109,9 @@ public open class ListPolynomialSpace>( .toMutableList() .apply { val result = getOrElse(0) { constantZero } - other - val isResultZero = result.isZero() - when { - size == 0 && !isResultZero -> add(result) - size > 1 || !isResultZero -> this[0] = result - else -> clear() - } + if(size == 0) add(result) + else this[0] = result } ) /** @@ -131,7 +123,8 @@ public open class ListPolynomialSpace>( if (other == 0) zero else ListPolynomial( coefficients - .applyAndRemoveZeros { + .toMutableList() + .apply { for (deg in indices) this[deg] = this[deg] * other } ) @@ -149,13 +142,9 @@ public open class ListPolynomialSpace>( .toMutableList() .apply { val result = this@plus + getOrElse(0) { constantZero } - val isResultZero = result.isZero() - when { - size == 0 && !isResultZero -> add(result) - size > 1 || !isResultZero -> this[0] = result - else -> clear() - } + if(size == 0) add(result) + else this[0] = result } ) /** @@ -173,13 +162,9 @@ public open class ListPolynomialSpace>( forEachIndexed { index, c -> if (index != 0) this[index] = -c } val result = this@minus - getOrElse(0) { constantZero } - val isResultZero = result.isZero() - when { - size == 0 && !isResultZero -> add(result) - size > 1 || !isResultZero -> this[0] = result - else -> clear() - } + if(size == 0) add(result) + else this[0] = result } ) /** @@ -191,7 +176,8 @@ public open class ListPolynomialSpace>( if (this == 0) zero else ListPolynomial( other.coefficients - .applyAndRemoveZeros { + .toMutableList() + .apply { for (deg in indices) this[deg] = this@times * this[deg] } ) @@ -205,20 +191,15 @@ public open class ListPolynomialSpace>( * Returns sum of the constant represented as polynomial and the polynomial. */ public override operator fun C.plus(other: ListPolynomial): ListPolynomial = - if (this.isZero()) other - else with(other.coefficients) { + 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) - val isResultZero = result.isZero() - when { - size == 0 && !isResultZero -> add(result) - size > 1 || !isResultZero -> this[0] = result - else -> clear() - } + if(size == 0) add(result) + else this[0] = result } ) } @@ -226,8 +207,7 @@ public open class ListPolynomialSpace>( * Returns difference between the constant represented as polynomial and the polynomial. */ public override operator fun C.minus(other: ListPolynomial): ListPolynomial = - if (this.isZero()) other - else with(other.coefficients) { + with(other.coefficients) { if (isEmpty()) ListPolynomial(listOf(this@minus)) else ListPolynomial( toMutableList() @@ -235,13 +215,9 @@ public open class ListPolynomialSpace>( forEachIndexed { index, c -> if (index != 0) this[index] = -c } val result = if (size == 0) this@minus else this@minus - get(0) - val isResultZero = result.isZero() - when { - size == 0 && !isResultZero -> add(result) - size > 1 || !isResultZero -> this[0] = result - else -> clear() - } + if(size == 0) add(result) + else this[0] = result } ) } @@ -249,10 +225,10 @@ public open class ListPolynomialSpace>( * Returns product of the constant represented as polynomial and the polynomial. */ public override operator fun C.times(other: ListPolynomial): ListPolynomial = - if (this.isZero()) other - else ListPolynomial( + ListPolynomial( other.coefficients - .applyAndRemoveZeros { + .toMutableList() + .apply { for (deg in indices) this[deg] = this@times * this[deg] } ) @@ -261,20 +237,15 @@ public open class ListPolynomialSpace>( * Returns sum of the constant represented as polynomial and the polynomial. */ public override operator fun ListPolynomial.plus(other: C): ListPolynomial = - if (other.isZero()) this - else with(coefficients) { + with(coefficients) { if (isEmpty()) ListPolynomial(listOf(other)) else ListPolynomial( toMutableList() .apply { val result = if (size == 0) other else get(0) + other - val isResultZero = result.isZero() - when { - size == 0 && !isResultZero -> add(result) - size > 1 || !isResultZero -> this[0] = result - else -> clear() - } + if(size == 0) add(result) + else this[0] = result } ) } @@ -282,20 +253,15 @@ public open class ListPolynomialSpace>( * Returns difference between the constant represented as polynomial and the polynomial. */ public override operator fun ListPolynomial.minus(other: C): ListPolynomial = - if (other.isZero()) this - else with(coefficients) { + with(coefficients) { if (isEmpty()) ListPolynomial(listOf(-other)) else ListPolynomial( toMutableList() .apply { val result = if (size == 0) other else get(0) - other - val isResultZero = result.isZero() - when { - size == 0 && !isResultZero -> add(result) - size > 1 || !isResultZero -> this[0] = result - else -> clear() - } + if(size == 0) add(result) + else this[0] = result } ) } @@ -303,10 +269,10 @@ public open class ListPolynomialSpace>( * Returns product of the constant represented as polynomial and the polynomial. */ public override operator fun ListPolynomial.times(other: C): ListPolynomial = - if (other.isZero()) this - else ListPolynomial( + ListPolynomial( coefficients - .applyAndRemoveZeros { + .toMutableList() + .apply { for (deg in indices) this[deg] = this[deg] * other } ) @@ -314,9 +280,7 @@ public open class ListPolynomialSpace>( /** * Converts the constant [value] to polynomial. */ - public override fun number(value: C): ListPolynomial = - if (value.isZero()) zero - else ListPolynomial(value) + public override fun number(value: C): ListPolynomial = ListPolynomial(value) /** * Returns negation of the polynomial. @@ -330,7 +294,7 @@ public open class ListPolynomialSpace>( val thisDegree = degree val otherDegree = other.degree return ListPolynomial( - Coefficients(max(thisDegree, otherDegree) + 1) { + List(max(thisDegree, otherDegree) + 1) { when { it > thisDegree -> other.coefficients[it] it > otherDegree -> coefficients[it] @@ -346,7 +310,7 @@ public open class ListPolynomialSpace>( val thisDegree = degree val otherDegree = other.degree return ListPolynomial( - Coefficients(max(thisDegree, otherDegree) + 1) { + List(max(thisDegree, otherDegree) + 1) { when { it > thisDegree -> -other.coefficients[it] it > otherDegree -> coefficients[it] @@ -361,39 +325,15 @@ public open class ListPolynomialSpace>( public override operator fun ListPolynomial.times(other: ListPolynomial): ListPolynomial { val thisDegree = degree val otherDegree = other.degree - return when { - thisDegree == -1 -> zero - otherDegree == -1 -> zero - else -> - ListPolynomial( - Coefficients(thisDegree + otherDegree + 1) { d -> - (max(0, d - otherDegree)..min(thisDegree, d)) - .map { coefficients[it] * other.coefficients[d - it] } - .reduce { acc, rational -> acc + rational } - } - ) - } + 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 } + } + ) } - /** - * Check if the instant is zero polynomial. - */ - public override fun ListPolynomial.isZero(): Boolean = coefficients.all { it.isZero() } - /** - * Check if the instant is unit polynomial. - */ - public override fun ListPolynomial.isOne(): Boolean = - with(coefficients) { - isNotEmpty() && withIndex().all { (index, c) -> if (index == 0) c.isOne() else c.isZero() } - } - /** - * Check if the instant is minus unit polynomial. - */ - public override fun ListPolynomial.isMinusOne(): Boolean = - with(coefficients) { - isNotEmpty() && withIndex().all { (index, c) -> if (index == 0) c.isMinusOne() else c.isZero() } - } - /** * Instance of zero polynomial (zero of the polynomial ring). */ @@ -403,34 +343,11 @@ public open class ListPolynomialSpace>( */ override val one: ListPolynomial = ListPolynomial(listOf(constantOne)) - /** - * Checks equality of the polynomials. - */ - public override infix fun ListPolynomial.equalsTo(other: ListPolynomial): Boolean = - when { - this === other -> true - this.degree == other.degree -> (0..degree).all { coefficients[it] == other.coefficients[it] } - else -> false - } - /** * 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.indexOfLast { it != constantZero } - - /** - * If polynomial is a constant polynomial represents and returns it as constant. - * Otherwise, (when the polynomial is not constant polynomial) returns `null`. - */ - public override fun ListPolynomial.asConstantOrNull(): C? = - with(coefficients) { - when { - isEmpty() -> constantZero - withIndex().all { (index, c) -> index == 0 || c.isZero() } -> first() - else -> null - } - } + public override val ListPolynomial.degree: Int get() = coefficients.lastIndex @Suppress("NOTHING_TO_INLINE") public inline fun ListPolynomial.substitute(argument: C): C = this.substitute(ring, argument) @@ -451,44 +368,6 @@ public open class ListPolynomialSpace>( public inline operator fun ListPolynomial.invoke(argument: C): C = this.substitute(ring, argument) @Suppress("NOTHING_TO_INLINE") public inline operator fun ListPolynomial.invoke(argument: ListPolynomial): ListPolynomial = this.substitute(ring, argument) - - // TODO: Move to other internal utilities with context receiver - @JvmName("applyAndRemoveZerosInternal") - internal inline fun MutableList.applyAndRemoveZeros(block: MutableList.() -> Unit) : MutableList { - contract { - callsInPlace(block, InvocationKind.EXACTLY_ONCE) - } - block() - while (isNotEmpty() && elementAt(lastIndex).isZero()) removeAt(lastIndex) - return this - } - internal inline fun List.applyAndRemoveZeros(block: MutableList.() -> Unit) : List = - toMutableList().applyAndRemoveZeros(block) - @Suppress("FunctionName") - internal inline fun MutableCoefficients(size: Int, init: (index: Int) -> C): MutableList { - val list = ArrayList(size) - repeat(size) { index -> list.add(init(index)) } - with(list) { while (isNotEmpty() && elementAt(lastIndex).isZero()) removeAt(lastIndex) } - return list - } - @Suppress("FunctionName") - internal inline fun Coefficients(size: Int, init: (index: Int) -> C): List = MutableCoefficients(size, init) - @OptIn(ExperimentalTypeInference::class) - internal inline fun buildCoefficients(@BuilderInference builderAction: MutableList.() -> Unit): List { - contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } - return buildList { - builderAction() - while (isNotEmpty() && elementAt(lastIndex).isZero()) removeAt(lastIndex) - } - } - @OptIn(ExperimentalTypeInference::class) - internal inline fun buildCoefficients(capacity: Int, @BuilderInference builderAction: MutableList.() -> Unit): List { - contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } - return buildList(capacity) { - builderAction() - while (isNotEmpty() && elementAt(lastIndex).isZero()) removeAt(lastIndex) - } - } } /** diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt index 67c7e9fa2..f62d1857f 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt @@ -8,7 +8,7 @@ package space.kscience.kmath.functions import space.kscience.kmath.operations.Ring -public data class ListRationalFunction internal constructor ( +public data class ListRationalFunction( public override val numerator: ListPolynomial, public override val denominator: ListPolynomial ) : RationalFunction> { @@ -17,25 +17,15 @@ public data class ListRationalFunction internal constructor ( // Waiting for context receivers :( TODO: Replace with context receivers when they will be available -@Suppress("FunctionName") -internal fun > ListRationalFunctionSpace.ListRationalFunction(numerator: ListPolynomial, denominator: ListPolynomial): ListRationalFunction = - if (denominator.isZero()) throw ArithmeticException("/ by zero") - else ListRationalFunction(numerator, denominator) -@Suppress("FunctionName") -internal fun > A.ListRationalFunction(numerator: ListPolynomial, denominator: ListPolynomial): ListRationalFunction = - if (denominator.coefficients.all { it == zero }) throw ArithmeticException("/ by zero") - else ListRationalFunction(numerator, denominator) @Suppress("FunctionName") public fun > ListRationalFunctionSpace.ListRationalFunction(numeratorCoefficients: List, denominatorCoefficients: List, reverse: Boolean = false): ListRationalFunction = - if (denominatorCoefficients.all { it == zero }) throw ArithmeticException("/ by zero") - else ListRationalFunction( + ListRationalFunction( ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), ListPolynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } ) ) @Suppress("FunctionName") public fun > A.ListRationalFunction(numeratorCoefficients: List, denominatorCoefficients: List, reverse: Boolean = false): ListRationalFunction = - if (denominatorCoefficients.all { it == zero }) throw ArithmeticException("/ by zero") - else ListRationalFunction( + ListRationalFunction( ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), ListPolynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } ) ) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index 80998d6bf..51f316c5d 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -58,6 +58,8 @@ internal fun List.cleanUp() = subList(0, indexOfLast { it != 0U } + 1) @Suppress("FunctionName", "NOTHING_TO_INLINE") internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(coefs, toCheckInput) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(coefs, toCheckInput) @Suppress("FunctionName") internal fun > A.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial { if (!toCheckInput) return NumberedPolynomial(coefs) @@ -70,13 +72,13 @@ internal fun > A.NumberedPolynomial(coefs: Map, C>, toC fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value } - return NumberedPolynomial( - fixedCoefs.filterValues { it != zero } - ) + return NumberedPolynomial(fixedCoefs) } @Suppress("FunctionName", "NOTHING_TO_INLINE") internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs, toCheckInput) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs, toCheckInput) @Suppress("FunctionName") internal fun > A.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial { if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) @@ -89,13 +91,13 @@ internal fun > A.NumberedPolynomial(pairs: Collection( - fixedCoefs.filterValues { it != zero } - ) + return NumberedPolynomial(fixedCoefs) } @Suppress("FunctionName", "NOTHING_TO_INLINE") internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs = pairs, toCheckInput = toCheckInput) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs = pairs, toCheckInput = toCheckInput) @Suppress("FunctionName") internal fun > A.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial { if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) @@ -108,25 +110,29 @@ internal fun > A.NumberedPolynomial(vararg pairs: Pair, fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value } - return NumberedPolynomial( - fixedCoefs.filterValues { it != zero } - ) + return NumberedPolynomial(fixedCoefs) } @Suppress("FunctionName") public fun > A.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) @Suppress("FunctionName") public fun > NumberedPolynomialSpace.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) +@Suppress("FunctionName") +public fun > NumberedRationalFunctionSpace.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) @Suppress("FunctionName") public fun > A.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) @Suppress("FunctionName") public fun > NumberedPolynomialSpace.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > NumberedRationalFunctionSpace.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) @Suppress("FunctionName") public fun > A.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) @Suppress("FunctionName") public fun > NumberedPolynomialSpace.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > NumberedRationalFunctionSpace.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) //context(A) //public fun > Symbol.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(mapOf(this to 1u) to one)) @@ -211,10 +217,7 @@ public open class NumberedPolynomialSpace>( .apply { val degs = emptyList() - val result = getOrElse(degs) { constantZero } + other - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = getOrElse(degs) { constantZero } + other } ) /** @@ -231,10 +234,7 @@ public open class NumberedPolynomialSpace>( .apply { val degs = emptyList() - val result = getOrElse(degs) { constantZero } - other - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = getOrElse(degs) { constantZero } - other } ) /** @@ -246,7 +246,8 @@ public open class NumberedPolynomialSpace>( if (other == 0) zero else NumberedPolynomial( coefficients - .applyAndRemoveZeros { + .toMutableMap() + .apply { for (degs in keys) this[degs] = this[degs]!! * other } ) @@ -265,10 +266,7 @@ public open class NumberedPolynomialSpace>( .apply { val degs = emptyList() - val result = this@plus + getOrElse(degs) { constantZero } - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = this@plus + getOrElse(degs) { constantZero } } ) /** @@ -285,10 +283,7 @@ public open class NumberedPolynomialSpace>( .apply { val degs = emptyList() - val result = this@minus - getOrElse(degs) { constantZero } - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = this@minus - getOrElse(degs) { constantZero } } ) /** @@ -300,7 +295,8 @@ public open class NumberedPolynomialSpace>( if (this == 0) zero else NumberedPolynomial( other.coefficients - .applyAndRemoveZeros { + .toMutableMap() + .apply { for (degs in keys) this[degs] = this@times * this[degs]!! } ) @@ -314,18 +310,14 @@ public open class NumberedPolynomialSpace>( * Returns sum of the constant represented as polynomial and the polynomial. */ override operator fun C.plus(other: NumberedPolynomial): NumberedPolynomial = - if (this.isZero()) other - else with(other.coefficients) { + with(other.coefficients) { if (isEmpty()) NumberedPolynomial(mapOf(emptyList() to this@plus)) else NumberedPolynomial( toMutableMap() .apply { val degs = emptyList() - val result = this@plus + getOrElse(degs) { constantZero } - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = this@plus + getOrElse(degs) { constantZero } } ) } @@ -333,8 +325,7 @@ public open class NumberedPolynomialSpace>( * Returns difference between the constant represented as polynomial and the polynomial. */ override operator fun C.minus(other: NumberedPolynomial): NumberedPolynomial = - if (this.isZero()) -other - else with(other.coefficients) { + with(other.coefficients) { if (isEmpty()) NumberedPolynomial(mapOf(emptyList() to this@minus)) else NumberedPolynomial( toMutableMap() @@ -343,10 +334,7 @@ public open class NumberedPolynomialSpace>( val degs = emptyList() - val result = this@minus - getOrElse(degs) { constantZero } - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = this@minus - getOrElse(degs) { constantZero } } ) } @@ -354,10 +342,10 @@ public open class NumberedPolynomialSpace>( * Returns product of the constant represented as polynomial and the polynomial. */ override operator fun C.times(other: NumberedPolynomial): NumberedPolynomial = - if (this.isZero()) zero - else NumberedPolynomial( + NumberedPolynomial( other.coefficients - .applyAndRemoveZeros { + .toMutableMap() + .apply { for (degs in keys) this[degs] = this@times * this[degs]!! } ) @@ -366,18 +354,14 @@ public open class NumberedPolynomialSpace>( * Returns sum of the constant represented as polynomial and the polynomial. */ override operator fun NumberedPolynomial.plus(other: C): NumberedPolynomial = - if (other.isZero()) this - else with(coefficients) { + with(coefficients) { if (isEmpty()) NumberedPolynomial(mapOf(emptyList() to other)) else NumberedPolynomial( toMutableMap() .apply { val degs = emptyList() - val result = getOrElse(degs) { constantZero } + other - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = getOrElse(degs) { constantZero } + other } ) } @@ -385,18 +369,14 @@ public open class NumberedPolynomialSpace>( * Returns difference between the constant represented as polynomial and the polynomial. */ override operator fun NumberedPolynomial.minus(other: C): NumberedPolynomial = - if (other.isZero()) this - else with(coefficients) { + with(coefficients) { if (isEmpty()) NumberedPolynomial(mapOf(emptyList() to other)) else NumberedPolynomial( toMutableMap() .apply { val degs = emptyList() - val result = getOrElse(degs) { constantZero } - other - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = getOrElse(degs) { constantZero } - other } ) } @@ -404,10 +384,10 @@ public open class NumberedPolynomialSpace>( * Returns product of the constant represented as polynomial and the polynomial. */ override operator fun NumberedPolynomial.times(other: C): NumberedPolynomial = - if (other.isZero()) zero - else NumberedPolynomial( + NumberedPolynomial( coefficients - .applyAndRemoveZeros { + .toMutableMap() + .apply { for (degs in keys) this[degs] = this[degs]!! * other } ) @@ -416,8 +396,7 @@ public open class NumberedPolynomialSpace>( * Converts the constant [value] to polynomial. */ public override fun number(value: C): NumberedPolynomial = - if (value == 0) zero - else NumberedPolynomial(mapOf(emptyList() to value)) + NumberedPolynomial(mapOf(emptyList() to value)) /** * Returns negation of the polynomial. @@ -431,7 +410,7 @@ public open class NumberedPolynomialSpace>( */ override operator fun NumberedPolynomial.plus(other: NumberedPolynomial): NumberedPolynomial = NumberedPolynomial( - buildCoefficients(coefficients.size + other.coefficients.size) { + buildMap(coefficients.size + other.coefficients.size) { other.coefficients.mapValuesTo(this) { it.value } other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value } } @@ -441,7 +420,7 @@ public open class NumberedPolynomialSpace>( */ override operator fun NumberedPolynomial.minus(other: NumberedPolynomial): NumberedPolynomial = NumberedPolynomial( - buildCoefficients(coefficients.size + other.coefficients.size) { + buildMap(coefficients.size + other.coefficients.size) { other.coefficients.mapValuesTo(this) { it.value } other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value } } @@ -450,57 +429,17 @@ public open class NumberedPolynomialSpace>( * Returns product of the polynomials. */ override operator fun NumberedPolynomial.times(other: NumberedPolynomial): NumberedPolynomial = - when { - isZero() -> zero - other.isZero() -> zero - else -> - NumberedPolynomial( - buildCoefficients(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 - this[degs] = if (degs in this) this[degs]!! + c else c - } - } - ) - } - - /** - * Check if the instant is zero polynomial. - */ - public override fun NumberedPolynomial.isZero(): Boolean = coefficients.values.all { it.isZero() } - /** - * Check if the instant is unit polynomial. - */ - public override fun NumberedPolynomial.isOne(): Boolean = - with(coefficients) { - var foundAbsoluteTermAndItIsOne = false - for ((degs, c) in this) { - if (degs.isNotEmpty()) if (c.isNotZero()) return@with false - else { - if (c.isNotOne()) return@with false - else foundAbsoluteTermAndItIsOne = true + NumberedPolynomial( + 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 + this[degs] = if (degs in this) this[degs]!! + c else c } } - foundAbsoluteTermAndItIsOne - } - /** - * Check if the instant is minus unit polynomial. - */ - public override fun NumberedPolynomial.isMinusOne(): Boolean = - with(coefficients) { - var foundAbsoluteTermAndItIsMinusOne = false - for ((degs, c) in this) { - if (degs.isNotEmpty()) if (c.isNotZero()) return@with false - else { - if (c.isNotMinusOne()) return@with false - else foundAbsoluteTermAndItIsMinusOne = true - } - } - foundAbsoluteTermAndItIsMinusOne - } + ) /** * Instance of zero polynomial (zero of the polynomial ring). @@ -516,28 +455,18 @@ public open class NumberedPolynomialSpace>( ) ) - /** - * Checks equality of the polynomials. - */ - override infix fun NumberedPolynomial.equalsTo(other: NumberedPolynomial): Boolean = - when { - this === other -> true - else -> coefficients.size == other.coefficients.size && - coefficients.all { (key, value) -> with(other.coefficients) { key in this && this[key] == value } } - } - /** * 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.entries.maxOfOrNull { (degs, c) -> if (c.isZero()) -1 else degs.lastIndex } ?: -1 + get() = coefficients.entries.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.entries.maxOfOrNull { (degs, c) -> if (c.isZero()) -1 else degs.sum().toInt() } ?: -1 + get() = coefficients.entries.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. @@ -548,8 +477,8 @@ public open class NumberedPolynomialSpace>( public val NumberedPolynomial.degrees: List get() = MutableList(lastVariable + 1) { 0u }.apply { - coefficients.entries.forEach { (degs, c) -> - if (c.isNotZero()) degs.forEachIndexed { index, deg -> + coefficients.entries.forEach { (degs, _) -> + degs.forEachIndexed { index, deg -> this[index] = max(this[index], deg) } } @@ -558,13 +487,13 @@ public open class NumberedPolynomialSpace>( * Counts degree of the polynomial by the specified [variable]. */ public fun NumberedPolynomial.degreeBy(variable: Int): UInt = - coefficients.entries.maxOfOrNull { (degs, c) -> if (c.isZero()) 0u else degs.getOrElse(variable) { 0u } } ?: 0u + coefficients.entries.maxOfOrNull { (degs, _) -> degs.getOrElse(variable) { 0u } } ?: 0u /** * Counts degree of the polynomial by the specified [variables]. */ public fun NumberedPolynomial.degreeBy(variables: Collection): UInt = - coefficients.entries.maxOfOrNull { (degs, c) -> - if (c.isZero()) 0u else degs.withIndex().filter { (index, _) -> index in variables }.sumOf { it.value } + coefficients.entries.maxOfOrNull { (degs, _) -> + degs.withIndex().filter { (index, _) -> index in variables }.sumOf { it.value } } ?: 0u /** * Count of variables occurring in the polynomial with positive power. If there is no such variable, @@ -573,43 +502,13 @@ public open class NumberedPolynomialSpace>( public val NumberedPolynomial.countOfVariables: Int get() = MutableList(lastVariable + 1) { false }.apply { - coefficients.entries.forEach { (degs, c) -> - if (c.isNotZero()) degs.forEachIndexed { index, deg -> + coefficients.entries.forEach { (degs, _) -> + degs.forEachIndexed { index, deg -> if (deg != 0u) this[index] = true } } }.count { it } - /** - * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. - */ - override fun NumberedPolynomial.isConstant(): Boolean = - coefficients.all { (degs, c) -> degs.isEmpty() || c.isZero() } - /** - * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. - */ - override fun NumberedPolynomial.isNonZeroConstant(): Boolean = - with(coefficients) { - var foundAbsoluteTermAndItIsNotZero = false - for ((degs, c) in this) { - if (degs.isNotEmpty()) if (c.isNotZero()) return@with false - else { - if (c.isZero()) return@with false - else foundAbsoluteTermAndItIsNotZero = true - } - } - foundAbsoluteTermAndItIsNotZero - } - /** - * If polynomial is a constant polynomial represents and returns it as constant. - * Otherwise, (when the polynomial is not constant polynomial) returns `null`. - */ - override fun NumberedPolynomial.asConstantOrNull(): C? = - with(coefficients) { - if(isConstant()) getOrElse(emptyList()) { constantZero } - else null - } - @Suppress("NOTHING_TO_INLINE") public inline fun NumberedPolynomial.substitute(argument: Map): NumberedPolynomial = this.substitute(ring, argument) @Suppress("NOTHING_TO_INLINE") @@ -629,35 +528,6 @@ public open class NumberedPolynomialSpace>( @JvmName("invokePolynomial") public inline operator fun NumberedPolynomial.invoke(argument: Map>): NumberedPolynomial = this.substitute(ring, argument) - // TODO: Move to other internal utilities with context receiver - @JvmName("applyAndRemoveZerosInternal") - internal fun MutableMap, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : MutableMap, C> { - contract { - callsInPlace(block, InvocationKind.EXACTLY_ONCE) - } - block() - for ((degs, c) in this) if (c.isZero()) this.remove(degs) - return this - } - internal fun Map, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : Map, C> = - toMutableMap().applyAndRemoveZeros(block) - @OptIn(ExperimentalTypeInference::class) - internal inline fun buildCoefficients(@BuilderInference builderAction: MutableMap, C>.() -> Unit): Map, C> { - contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } - return buildMap { - builderAction() - for ((degs, c) in this) if (c.isZero()) this.remove(degs) - } - } - @OptIn(ExperimentalTypeInference::class) - internal inline fun buildCoefficients(capacity: Int, @BuilderInference builderAction: MutableMap, C>.() -> Unit): Map, C> { - contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } - return buildMap(capacity) { - builderAction() - for ((degs, c) in this) if (c.isZero()) this.remove(degs) - } - } - // TODO: Move to other constructors with context receiver public fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(emptyList() to this)) } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt index 2a4d942a6..b4d9f1d91 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt @@ -19,45 +19,35 @@ public class NumberedRationalFunction internal constructor( // Waiting for context receivers :( TODO: Replace with context receivers when they will be available -@Suppress("FunctionName") -internal fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numerator: NumberedPolynomial, denominator: NumberedPolynomial): NumberedRationalFunction = - if (denominator.isZero()) throw ArithmeticException("/ by zero") - else NumberedRationalFunction(numerator, denominator) -@Suppress("FunctionName") -internal fun > A.NumberedRationalFunction(numerator: NumberedPolynomial, denominator: NumberedPolynomial): NumberedRationalFunction = - if (denominator.coefficients.values.all { it == zero }) throw ArithmeticException("/ by zero") - else NumberedRationalFunction(numerator, denominator) @Suppress("FunctionName") public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): NumberedRationalFunction = - if (denominatorCoefficients.values.all { it == zero }) throw ArithmeticException("/ by zero") - else NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients), - NumberedPolynomial(denominatorCoefficients) + NumberedRationalFunction( + NumberedPolynomial(numeratorCoefficients, toCheckInput = true), + NumberedPolynomial(denominatorCoefficients, toCheckInput = true) ) @Suppress("FunctionName") public fun > A.NumberedRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): NumberedRationalFunction = - if (denominatorCoefficients.values.all { it == zero }) throw ArithmeticException("/ by zero") - else NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients), - NumberedPolynomial(denominatorCoefficients) + NumberedRationalFunction( + NumberedPolynomial(numeratorCoefficients, toCheckInput = true), + NumberedPolynomial(denominatorCoefficients, toCheckInput = true) ) @Suppress("FunctionName") public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numerator: NumberedPolynomial): NumberedRationalFunction = NumberedRationalFunction(numerator, polynomialOne) @Suppress("FunctionName") public fun > A.NumberedRationalFunction(numerator: NumberedPolynomial): NumberedRationalFunction = - NumberedRationalFunction(numerator, NumberedPolynomial(mapOf(emptyList() to one))) + NumberedRationalFunction(numerator, NumberedPolynomial(mapOf(emptyList() to one), toCheckInput = false)) @Suppress("FunctionName") public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numeratorCoefficients: Map, C>): NumberedRationalFunction = NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients), + NumberedPolynomial(numeratorCoefficients, toCheckInput = true), polynomialOne ) @Suppress("FunctionName") public fun > A.NumberedRationalFunction(numeratorCoefficients: Map, C>): NumberedRationalFunction = NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients), - NumberedPolynomial(mapOf(emptyList() to one)) + NumberedPolynomial(numeratorCoefficients, toCheckInput = true), + NumberedPolynomial(mapOf(emptyList() to one), toCheckInput = false) ) public class NumberedRationalFunctionSpace> ( @@ -91,28 +81,6 @@ public class NumberedRationalFunctionSpace> ( */ public override val one: NumberedRationalFunction = NumberedRationalFunction(polynomialOne, polynomialOne) - /** - * Checks equality of the rational functions. - */ - public override infix fun NumberedRationalFunction.equalsTo(other: NumberedRationalFunction): Boolean { - if (this === other) return true - - if (numerator.isZero() != other.numerator.isZero()) return false - - val countOfVariables = max(this.lastVariable, other.lastVariable) - val thisNumeratorDegrees = this.numerator.degrees - val thisDenominatorDegrees = this.denominator.degrees - val otherNumeratorDegrees = other.numerator.degrees - val otherDenominatorDegrees = other.denominator.degrees - for (variable in 0 .. countOfVariables) - if ( - thisNumeratorDegrees.getOrElse(variable) { 0u } + otherDenominatorDegrees.getOrElse(variable) { 0u } - != thisDenominatorDegrees.getOrElse(variable) { 0u } + otherNumeratorDegrees.getOrElse(variable) { 0u } - ) return false - - return numerator * other.denominator equalsTo other.numerator * denominator - } - /** * Maximal index (ID) of variable occurring in the polynomial with positive power. If there is no such variable, * the result is `-1`. @@ -152,13 +120,13 @@ public class NumberedRationalFunctionSpace> ( public val NumberedRationalFunction.countOfVariables: Int get() = MutableList(lastVariable + 1) { false }.apply { - numerator.coefficients.entries.forEach { (degs, c) -> - if (c.isNotZero()) degs.forEachIndexed { index, deg -> + numerator.coefficients.entries.forEach { (degs, _) -> + degs.forEachIndexed { index, deg -> if (deg != 0u) this[index] = true } } - denominator.coefficients.entries.forEach { (degs, c) -> - if (c.isNotZero()) degs.forEachIndexed { index, deg -> + denominator.coefficients.entries.forEach { (degs, _) -> + degs.forEachIndexed { index, deg -> if (deg != 0u) this[index] = true } } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index d44c47dd6..96e860550 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -155,31 +155,6 @@ public interface PolynomialSpace> : Ring

{ @JsName("constantPower") public fun power(arg: C, exponent: UInt) : C - /** - * Check if the instant is zero constant. - */ - public fun C.isZero(): Boolean = this == constantZero - /** - * Check if the instant is NOT zero constant. - */ - public fun C.isNotZero(): Boolean = !isZero() - /** - * Check if the instant is unit constant. - */ - public fun C.isOne(): Boolean = this == constantOne - /** - * Check if the instant is NOT unit constant. - */ - public fun C.isNotOne(): Boolean = !isOne() - /** - * Check if the instant is minus unit constant. - */ - public fun C.isMinusOne(): Boolean = this == -constantOne - /** - * Check if the instant is NOT minus unit constant. - */ - public fun C.isNotMinusOne(): Boolean = !isMinusOne() - /** * Instance of zero constant (zero of the underlying ring). */ @@ -249,31 +224,6 @@ public interface PolynomialSpace> : Ring

{ */ public override fun power(arg: P, exponent: UInt) : P = exponentiationBySquaring(arg, exponent) - /** - * Check if the instant is zero polynomial. - */ - public fun P.isZero(): Boolean = this equalsTo zero - /** - * Check if the instant is NOT zero polynomial. - */ - public fun P.isNotZero(): Boolean = !isZero() - /** - * Check if the instant is unit polynomial. - */ - public fun P.isOne(): Boolean = this equalsTo one - /** - * Check if the instant is NOT unit polynomial. - */ - public fun P.isNotOne(): Boolean = !isOne() - /** - * Check if the instant is minus unit polynomial. - */ - public fun P.isMinusOne(): Boolean = this equalsTo -one - /** - * Check if the instant is NOT minus unit polynomial. - */ - public fun P.isNotMinusOne(): Boolean = !isMinusOne() - /** * Instance of zero polynomial (zero of the polynomial ring). */ @@ -283,48 +233,12 @@ public interface PolynomialSpace> : Ring

{ */ public override val one: P - /** - * Checks equality of the polynomials. - */ - public infix fun P.equalsTo(other: P): Boolean - /** - * Checks NOT equality of the polynomials. - */ - public infix fun P.notEqualsTo(other: P): Boolean = !(this equalsTo other) - /** * 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 - /** - * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. - */ - public fun P.isConstant(): Boolean = degree <= 0 - /** - * Checks if the instant is **not** constant polynomial (of degree no more than 0) over considered ring. - */ - public fun P.isNotConstant(): Boolean = !isConstant() - /** - * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. - */ - public fun P.isNonZeroConstant(): Boolean = degree == 0 - /** - * Checks if the instant is **not** constant non-zero polynomial (of degree no more than 0) over considered ring. - */ - public fun P.isNotNonZeroConstant(): Boolean = !isNonZeroConstant() - /** - * If polynomial is a constant polynomial represents and returns it as constant. - * Otherwise, (when the polynomial is not constant polynomial) returns `null`. - */ - public fun P.asConstantOrNull(): C? - /** - * If polynomial is a constant polynomial represents and returns it as constant. - * Otherwise, (when the polynomial is not constant polynomial) raises corresponding exception. - */ - public fun P.asConstant(): C = requireNotNull(asConstantOrNull()) { "Can not represent non-constant polynomial as a constant" } - override fun add(left: P, right: P): P = left + right override fun multiply(left: P, right: P): P = left * right } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index 9c0263c4c..374f4a936 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -222,31 +222,6 @@ public interface RationalFunctionalSpace, R: RationalFunctio @JsName("constantPower") public fun power(arg: C, exponent: UInt) : C - /** - * Check if the instant is zero constant. - */ - public fun C.isZero(): Boolean = this == constantZero - /** - * Check if the instant is NOT zero constant. - */ - public fun C.isNotZero(): Boolean = !isZero() - /** - * Check if the instant is unit constant. - */ - public fun C.isOne(): Boolean = this == constantOne - /** - * Check if the instant is NOT unit constant. - */ - public fun C.isNotOne(): Boolean = !isOne() - /** - * Check if the instant is minus unit constant. - */ - public fun C.isMinusOne(): Boolean = this == -constantOne - /** - * Check if the instant is NOT minus unit constant. - */ - public fun C.isNotMinusOne(): Boolean = !isMinusOne() - /** * Instance of zero constant (zero of the underlying ring). */ @@ -320,31 +295,6 @@ public interface RationalFunctionalSpace, R: RationalFunctio */ public fun power(arg: P, exponent: UInt) : P - /** - * Check if the instant is zero polynomial. - */ - public fun P.isZero(): Boolean = this equalsTo polynomialZero - /** - * Check if the instant is NOT zero polynomial. - */ - public fun P.isNotZero(): Boolean = !isZero() - /** - * Check if the instant is unit polynomial. - */ - public fun P.isOne(): Boolean = this equalsTo polynomialOne - /** - * Check if the instant is NOT unit polynomial. - */ - public fun P.isNotOne(): Boolean = !isOne() - /** - * Check if the instant is minus unit polynomial. - */ - public fun P.isMinusOne(): Boolean = this equalsTo -polynomialOne - /** - * Check if the instant is NOT minus unit polynomial. - */ - public fun P.isNotMinusOne(): Boolean = !isMinusOne() - /** * Instance of zero polynomial (zero of the polynomial ring). */ @@ -354,15 +304,6 @@ public interface RationalFunctionalSpace, R: RationalFunctio */ public val polynomialOne: P - /** - * Checks equality of the polynomials. - */ - public infix fun P.equalsTo(other: P): Boolean - /** - * Checks NOT equality of the polynomials. - */ - public infix fun P.notEqualsTo(other: P): Boolean = !(this equalsTo other) - /** * Returns sum of the constant represented as rational function and the rational function. */ @@ -478,31 +419,6 @@ public interface RationalFunctionalSpace, R: RationalFunctio */ public override fun power(arg: R, exponent: UInt) : R = exponentiationBySquaring(arg, exponent) - /** - * Check if the instant is zero rational function. - */ - public fun R.isZero(): Boolean = numerator equalsTo polynomialZero - /** - * Check if the instant is NOT zero rational function. - */ - public fun R.isNotZero(): Boolean = !isZero() - /** - * Check if the instant is unit rational function. - */ - public fun R.isOne(): Boolean = numerator equalsTo denominator - /** - * Check if the instant is NOT unit rational function. - */ - public fun R.isNotOne(): Boolean = !isOne() - /** - * Check if the instant is minus unit rational function. - */ - public fun R.isMinusOne(): Boolean = (numerator + denominator).isZero() - /** - * Check if the instant is NOT minus unit rational function. - */ - public fun R.isNotMinusOne(): Boolean = !isMinusOne() - /** * Instance of zero rational function (zero of the rational functions ring). */ @@ -512,54 +428,12 @@ public interface RationalFunctionalSpace, R: RationalFunctio */ public override val one: R - /** - * Checks equality of the rational functions. - */ - public infix fun R.equalsTo(other: R): Boolean = - when { - this === other -> true - numerator.isZero() != other.numerator.isZero() -> false - numeratorDegree - denominatorDegree != with(other) { numeratorDegree - denominatorDegree } -> false - else -> numerator * other.denominator equalsTo other.numerator * denominator - } - /** - * Checks NOT equality of the polynomials. - */ - public infix fun R.notEqualsTo(other: R): Boolean = !(this equalsTo other) - /** * 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 - /** - * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. - */ - public fun P.isConstant(): Boolean = degree <= 0 - /** - * Checks if the instant is **not** constant polynomial (of degree no more than 0) over considered ring. - */ - public fun P.isNotConstant(): Boolean = !isConstant() - /** - * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. - */ - public fun P.isNonZeroConstant(): Boolean = degree == 0 - /** - * Checks if the instant is **not** constant non-zero polynomial (of degree no more than 0) over considered ring. - */ - public fun P.isNotNonZeroConstant(): Boolean = !isNonZeroConstant() - /** - * If polynomial is a constant polynomial represents and returns it as constant. - * Otherwise, (when the polynomial is not constant polynomial) returns `null`. - */ - public fun P.asConstantOrNull(): C? - /** - * If polynomial is a constant polynomial represents and returns it as constant. - * Otherwise, (when the polynomial is not constant polynomial) raises corresponding exception. - */ - public fun P.asConstant(): C = requireNotNull(asConstantOrNull()) { "Can not represent non-constant polynomial as a constant" } - /** * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is * zero, degree is -1. @@ -813,31 +687,6 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< @JvmName("constantPower") public override fun power(arg: C, exponent: UInt) : C = polynomialRing { power(arg, exponent) } - /** - * Check if the instant is zero constant. - */ - public override fun C.isZero(): Boolean = polynomialRing { this@isZero.isZero() } - /** - * Check if the instant is NOT zero constant. - */ - public override fun C.isNotZero(): Boolean = polynomialRing { this@isNotZero.isNotZero() } - /** - * Check if the instant is unit constant. - */ - public override fun C.isOne(): Boolean = polynomialRing { this@isOne.isOne() } - /** - * Check if the instant is NOT unit constant. - */ - public override fun C.isNotOne(): Boolean = polynomialRing { this@isNotOne.isNotOne() } - /** - * Check if the instant is minus unit constant. - */ - public override fun C.isMinusOne(): Boolean = polynomialRing { this@isMinusOne.isMinusOne() } - /** - * Check if the instant is NOT minus unit constant. - */ - public override fun C.isNotMinusOne(): Boolean = polynomialRing { this@isNotMinusOne.isNotMinusOne() } - /** * Instance of zero constant (zero of the underlying ring). */ @@ -907,31 +756,6 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< */ public override fun power(arg: P, exponent: UInt) : P = polynomialRing { power(arg, exponent) } - /** - * Check if the instant is zero polynomial. - */ - public override fun P.isZero(): Boolean = polynomialRing { this@isZero.isZero() } - /** - * Check if the instant is NOT zero polynomial. - */ - public override fun P.isNotZero(): Boolean = polynomialRing { this@isNotZero.isNotZero() } - /** - * Check if the instant is unit polynomial. - */ - public override fun P.isOne(): Boolean = polynomialRing { this@isOne.isOne() } - /** - * Check if the instant is NOT unit polynomial. - */ - public override fun P.isNotOne(): Boolean = polynomialRing { this@isNotOne.isNotOne() } - /** - * Check if the instant is minus unit polynomial. - */ - public override fun P.isMinusOne(): Boolean = polynomialRing { this@isMinusOne.isMinusOne() } - /** - * Check if the instant is NOT minus unit polynomial. - */ - public override fun P.isNotMinusOne(): Boolean = polynomialRing { this@isNotMinusOne.isNotMinusOne() } - /** * Instance of zero polynomial (zero of the polynomial ring). */ @@ -941,47 +765,11 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< */ public override val polynomialOne: P get() = polynomialRing.one - /** - * Checks equality of the polynomials. - */ - public override infix fun P.equalsTo(other: P): Boolean = polynomialRing { this@equalsTo equalsTo other } - /** - * Checks NOT equality of the polynomials. - */ - public override infix fun P.notEqualsTo(other: P): Boolean = polynomialRing { this@notEqualsTo notEqualsTo other } - /** * 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 } - - /** - * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. - */ - public override fun P.isConstant(): Boolean = polynomialRing { this@isConstant.isConstant() } - /** - * Checks if the instant is **not** constant polynomial (of degree no more than 0) over considered ring. - */ - public override fun P.isNotConstant(): Boolean = polynomialRing { this@isNotConstant.isNotConstant() } - /** - * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. - */ - public override fun P.isNonZeroConstant(): Boolean = polynomialRing { this@isNonZeroConstant.isNonZeroConstant() } - /** - * Checks if the instant is **not** constant non-zero polynomial (of degree no more than 0) over considered ring. - */ - public override fun P.isNotNonZeroConstant(): Boolean = polynomialRing { this@isNotNonZeroConstant.isNotNonZeroConstant() } - /** - * If polynomial is a constant polynomial represents and returns it as constant. - * Otherwise, (when the polynomial is not constant polynomial) returns `null`. - */ - public override fun P.asConstantOrNull(): C? = polynomialRing { this@asConstantOrNull.asConstantOrNull() } - /** - * If polynomial is a constant polynomial represents and returns it as constant. - * Otherwise, (when the polynomial is not constant polynomial) raises corresponding exception. - */ - public override fun P.asConstant(): C = polynomialRing { this@asConstant.asConstant() } } /** @@ -1032,18 +820,11 @@ public abstract class PolynomialSpaceOfFractions< denominator ) - public override operator fun R.div(other: Int): R { - val otherAsConstant = constantNumber(other) - require(otherAsConstant.isNotZero()) { "/ by zero." } - return constructRationalFunction( + public override operator fun R.div(other: Int): R = + constructRationalFunction( numerator, - (denominator * other).also { - check(it.isNotZero()) { - "Got zero denominator during division of rational functions to constant. It means underlying ring of polynomials is not integral domain." - } - } + denominator * other ) - } /** * Returns sum of the integer represented as rational function and the rational function. @@ -1076,13 +857,11 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) - public override operator fun Int.div(other: R): R { - require(other.numerator.isNotZero()) { "/ by zero." } - return constructRationalFunction( + public override operator fun Int.div(other: R): R = + constructRationalFunction( this * other.denominator, other.numerator ) - } /** * Converts the integer [value] to rational function. @@ -1119,13 +898,11 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) - public override operator fun C.div(other: R): R { - require(other.numerator.isNotZero()) { "/ by zero." } - return constructRationalFunction( + public override operator fun C.div(other: R): R = + constructRationalFunction( this * other.denominator, other.numerator ) - } /** * Returns sum of the constant represented as rational function and the rational function. @@ -1152,17 +929,11 @@ public abstract class PolynomialSpaceOfFractions< denominator ) - public override operator fun R.div(other: C): R { - require(other.isNotZero()) { "/ by zero." } - return constructRationalFunction( + public override operator fun R.div(other: C): R = + constructRationalFunction( numerator, - (denominator * other).also { - check(it.isNotZero()) { - "Got zero denominator during division of rational functions to constant. It means underlying ring of polynomials is not integral domain." - } - } + denominator * other ) - } /** * Converts the constant [value] to rational function. @@ -1194,13 +965,11 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) - public override operator fun P.div(other: R): R { - require(other.numerator.isNotZero()) { "/ by zero." } - return constructRationalFunction( + public override operator fun P.div(other: R): R = + constructRationalFunction( this * other.denominator, other.numerator ) - } /** * Returns sum of the polynomial represented as rational function and the rational function. @@ -1227,17 +996,11 @@ public abstract class PolynomialSpaceOfFractions< denominator ) - public override operator fun R.div(other: P): R { - require(other.isNotZero()) { "/ by zero." } - return constructRationalFunction( + public override operator fun R.div(other: P): R = + constructRationalFunction( numerator, - (denominator * other).also { - require(it.isNotZero()) { - "Got zero denominator during division of rational functions to polynomial. It means underlying ring of polynomials is not integral domain." - } - } + denominator * other ) - } /** * Converts the polynomial [value] to rational function. @@ -1254,11 +1017,7 @@ public abstract class PolynomialSpaceOfFractions< public override operator fun R.plus(other: R): R = constructRationalFunction( numerator * other.denominator + denominator * other.numerator, - (denominator * other.denominator).also { - check(it.isNotZero()) { - "Got zero denominator during addition of rational functions. It means underlying ring of polynomials is not integral domain." - } - } + denominator * other.denominator ) /** * Returns difference of the rational functions. @@ -1266,11 +1025,7 @@ public abstract class PolynomialSpaceOfFractions< public override operator fun R.minus(other: R): R = constructRationalFunction( numerator * other.denominator - denominator * other.numerator, - (denominator * other.denominator).also { - check(it.isNotZero()) { - "Got zero denominator during subtraction of rational functions. It means underlying ring of polynomials is not integral domain." - } - } + denominator * other.denominator ) /** * Returns product of the rational functions. @@ -1278,24 +1033,14 @@ public abstract class PolynomialSpaceOfFractions< public override operator fun R.times(other: R): R = constructRationalFunction( numerator * other.numerator, - (denominator * other.denominator).also { - check(it.isNotZero()) { - "Got zero denominator during multiplication of rational functions. It means underlying ring of polynomials is not integral domain." - } - } + denominator * other.denominator ) - public override operator fun R.div(other: R): R { - require(other.isNotZero()) { "/ by zero." } - return constructRationalFunction( + public override operator fun R.div(other: R): R = + constructRationalFunction( numerator * other.denominator, - (denominator * other.numerator).also { - check(it.isNotZero()) { - "Got zero denominator during division of rational functions. It means underlying ring of polynomials is not integral domain." - } - } + denominator * other.numerator ) - } /** * Instance of zero rational function (zero of the rational functions ring). diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt index 35155d09d..50313cab9 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt @@ -121,9 +121,9 @@ public fun ListPolynomial.substitute(ring: Ring, arg: C): C = ring { public fun ListPolynomial.substitute(ring: Ring, arg: ListPolynomial) : ListPolynomial = ring { if (coefficients.isEmpty()) return ListPolynomial(emptyList()) - val thisDegree = coefficients.indexOfLast { it != zero } + val thisDegree = coefficients.lastIndex if (thisDegree == -1) return ListPolynomial(emptyList()) - val argDegree = arg.coefficients.indexOfLast { it != zero } + val argDegree = arg.coefficients.lastIndex if (argDegree == -1) return coefficients[0].asListPolynomial() val constantZero = zero val resultCoefs: MutableList = MutableList(thisDegree * argDegree + 1) { constantZero } @@ -144,7 +144,6 @@ public fun ListPolynomial.substitute(ring: Ring, arg: ListPolynomial(resultCoefs) } @@ -168,7 +167,6 @@ public fun ListPolynomial.derivative( ListPolynomial( buildList(max(0, coefficients.size - 1)) { for (deg in 1 .. coefficients.lastIndex) add(number(deg) * coefficients[deg]) - while (isNotEmpty() && elementAt(lastIndex) == algebra.zero) removeAt(lastIndex) } ) } @@ -186,7 +184,6 @@ public fun ListPolynomial.nthDerivative( 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) }) - while (isNotEmpty() && elementAt(lastIndex) == algebra.zero) removeAt(lastIndex) } ) } @@ -202,7 +199,6 @@ public fun ListPolynomial.antiderivative( buildList(coefficients.size + 1) { add(zero) coefficients.mapIndexedTo(this) { index, t -> t / number(index + 1) } - while (isNotEmpty() && elementAt(lastIndex) == algebra.zero) removeAt(lastIndex) } ) } @@ -220,7 +216,6 @@ public fun ListPolynomial.nthAntiderivative( buildList(coefficients.size + order) { repeat(order) { add(zero) } coefficients.mapIndexedTo(this) { index, c -> (1..order).fold(c) { acc, i -> acc / number(index + i) } } - while (isNotEmpty() && elementAt(lastIndex) == algebra.zero) removeAt(lastIndex) } ) } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listRationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listRationalFunctionUtil.kt index 151c7bb8d..367212588 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listRationalFunctionUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listRationalFunctionUtil.kt @@ -55,11 +55,11 @@ public fun ListRationalFunction.substitute(ring: Field, arg: C): C = r internal fun ListPolynomial.substituteRationalFunctionTakeNumerator(ring: Ring, arg: ListRationalFunction): ListPolynomial = ring { if (coefficients.isEmpty()) return ListPolynomial(emptyList()) - val thisDegree = coefficients.indexOfLast { it != zero } + val thisDegree = coefficients.lastIndex if (thisDegree == -1) return ListPolynomial(emptyList()) val thisDegreeLog2 = 31 - thisDegree.countLeadingZeroBits() - val numeratorDegree = arg.numerator.coefficients.indexOfLast { it != zero } - val denominatorDegree = arg.denominator.coefficients.indexOfLast { it != zero } + val numeratorDegree = arg.numerator.coefficients.lastIndex + val denominatorDegree = arg.denominator.coefficients.lastIndex val argDegree = max(numeratorDegree, denominatorDegree) val constantZero = zero val powersOf2 = buildList(thisDegreeLog2 + 1) { diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt index 0d2c4b5fc..ac2647592 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt @@ -9,7 +9,7 @@ import space.kscience.kmath.test.misc.* import kotlin.test.* -class ListPolynomialTest { +class ListPolynomialTest { // TODO: Adapt tests to changes @Test fun test_Polynomial_Int_plus() { RationalField.listPolynomial { @@ -489,94 +489,6 @@ class ListPolynomialTest { } } @Test - fun test_Polynomial_isZero() { - RationalField.listPolynomial { - assertTrue("test 1") { ListPolynomial().isZero() } - assertTrue("test 2") { ListPolynomial(Rational(0)).isZero() } - assertTrue("test 3") { ListPolynomial(Rational(0), Rational(0)).isZero() } - assertTrue("test 4") { ListPolynomial(Rational(0), Rational(0), Rational(0)) - .isZero() } - assertFalse("test 5") { ListPolynomial(Rational(3, 5)).isZero() } - assertFalse("test 6") { ListPolynomial(Rational(3, 5), Rational(0)) - .isZero() } - assertFalse("test 7") { ListPolynomial(Rational(0), Rational(3, 5), Rational(0)) - .isZero() } - } - } - @Test - fun test_Polynomial_isOne() { - RationalField.listPolynomial { - assertFalse("test 1") { ListPolynomial().isOne() } - assertFalse("test 2") { ListPolynomial(Rational(0)).isOne() } - assertFalse("test 3") { ListPolynomial(Rational(0), Rational(0)).isOne() } - assertFalse("test 4") { ListPolynomial(Rational(0), Rational(0), Rational(0)) - .isOne() } - assertFalse("test 5") { ListPolynomial(Rational(3, 5)).isOne() } - assertTrue("test 6") { ListPolynomial(Rational(5, 5)).isOne() } - assertFalse("test 7") { ListPolynomial(Rational(3, 5), Rational(0)).isOne() } - assertTrue("test 8") { ListPolynomial(Rational(3, 3), Rational(0)).isOne() } - assertFalse("test 9") { ListPolynomial(Rational(0), Rational(3, 5), Rational(0)) - .isOne() } - assertFalse("test 10") { ListPolynomial(Rational(0), Rational(5, 5), Rational(0)) - .isOne() } - assertFalse("test 11") { ListPolynomial(Rational(1), Rational(3, 5), Rational(0)) - .isOne() } - assertFalse("test 12") { ListPolynomial(Rational(1), Rational(5, 5), Rational(0)) - .isOne() } - } - } - @Test - fun test_Polynomial_isMinusOne() { - RationalField.listPolynomial { - assertFalse("test 1") { ListPolynomial().isMinusOne() } - assertFalse("test 2") { ListPolynomial(Rational(0)).isMinusOne() } - assertFalse("test 3") { ListPolynomial(Rational(0), Rational(0)).isMinusOne() } - assertFalse("test 4") { ListPolynomial(Rational(0), Rational(0), Rational(0)) - .isMinusOne() } - assertFalse("test 5") { ListPolynomial(Rational(3, 5)).isMinusOne() } - assertTrue("test 6") { ListPolynomial(Rational(-5, 5)).isMinusOne() } - assertFalse("test 7") { ListPolynomial(Rational(3, 5), Rational(0)).isMinusOne() } - assertTrue("test 8") { ListPolynomial(Rational(-3, 3), Rational(0)).isMinusOne() } - assertFalse("test 9") { ListPolynomial(Rational(0), Rational(3, 5), Rational(0)) - .isMinusOne() } - assertFalse("test 10") { ListPolynomial(Rational(0), Rational(5, -5), Rational(0)) - .isMinusOne() } - assertFalse("test 11") { ListPolynomial(Rational(-1), Rational(3, 5), Rational(0)) - .isMinusOne() } - assertFalse("test 12") { ListPolynomial(Rational(-1), Rational(5, -5), Rational(0)) - .isMinusOne() } - } - } - @Test - fun test_Polynomial_Polynomial_equalsTo() { - RationalField.listPolynomial { - assertTrue("test 1") { - ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) equalsTo - ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - } - assertTrue("test 2") { - ListPolynomial(Rational(5, 9), Rational(0), Rational(-8, 7)) equalsTo - ListPolynomial(Rational(5, 9), Rational(0), Rational(-8, 7)) - } - assertTrue("test 3") { - ListPolynomial(Rational(0), Rational(0), Rational(-8, 7), Rational(0), Rational(0)) equalsTo - ListPolynomial(Rational(0), Rational(0), Rational(-8, 7)) - } - assertFalse("test 4") { - ListPolynomial(Rational(5, 9), Rational(5, 7), Rational(-8, 7)) equalsTo - ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - } - assertFalse("test 5") { - ListPolynomial(Rational(8, 3), Rational(0), Rational(-8, 7)) equalsTo - ListPolynomial(Rational(5, 9), Rational(0), Rational(-8, 7)) - } - assertFalse("test 6") { - ListPolynomial(Rational(0), Rational(0), Rational(-8, 7), Rational(0), Rational(0)) equalsTo - ListPolynomial(Rational(0), Rational(0), Rational(8, 7)) - } - } - } - @Test fun test_Polynomial_degree() { RationalField.listPolynomial { assertEquals( @@ -636,70 +548,4 @@ class ListPolynomialTest { ) } } - @Test - fun test_Polynomial_asConstantOrNull() { - RationalField.listPolynomial { - assertEquals( - Rational(0), - ListPolynomial().asConstantOrNull(), - "test 1" - ) - assertEquals( - Rational(0), - ListPolynomial(Rational(0)).asConstantOrNull(), - "test 2" - ) - assertEquals( - Rational(0), - ListPolynomial(Rational(0), Rational(0)).asConstantOrNull(), - "test 3" - ) - assertEquals( - Rational(0), - ListPolynomial(Rational(0), Rational(0), Rational(0)).asConstantOrNull(), - "test 4" - ) - assertEquals( - Rational(-7, 9), - ListPolynomial(Rational(-7, 9)).asConstantOrNull(), - "test 5" - ) - assertEquals( - Rational(-7, 9), - ListPolynomial(Rational(-7, 9), Rational(0)).asConstantOrNull(), - "test 6" - ) - assertEquals( - Rational(-7, 9), - ListPolynomial(Rational(-7, 9), Rational(0), Rational(0)).asConstantOrNull(), - "test 7" - ) - assertEquals( - null, - ListPolynomial(Rational(0), Rational(-7, 9)).asConstantOrNull(), - "test 8" - ) - assertEquals( - null, - ListPolynomial(Rational(0), Rational(-7, 9), Rational(0)).asConstantOrNull(), - "test 9" - ) - assertEquals( - null, - ListPolynomial(Rational(0), Rational(0), Rational(-7, 9)).asConstantOrNull(), - "test 10" - ) - assertEquals( - null, - ListPolynomial(Rational(4, 15), Rational(0), Rational(-7, 9)).asConstantOrNull(), - "test 11" - ) - assertEquals( - null, - ListPolynomial(Rational(4, 15), Rational(0), Rational(-7, 9), Rational(0)) - .asConstantOrNull(), - "test 12" - ) - } - } } \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt index 50ae18260..c4f07d957 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt @@ -12,7 +12,7 @@ import kotlin.test.assertEquals import kotlin.test.assertFailsWith -class ListPolynomialUtilTest { +class ListPolynomialUtilTest { // TODO: Adapt tests to changes @Test fun test_substitute_Double() { assertEquals( -- 2.34.1 From 7e328a5dbf936256a4612f582b5802b3d8e5a9aa Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Fri, 25 Mar 2022 00:59:48 +0300 Subject: [PATCH 064/275] Enhanced DSL constructor a bit. --- .../space/kscience/kmath/functions/NumberedPolynomial.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index 51f316c5d..f931e8e7e 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -157,7 +157,8 @@ public class NumberedPolynomialTermSignatureBuilder { signature[this] = deg } } - public infix fun Int.to(deg: UInt): Unit = this inPowerOf deg + public infix fun Int.pow(deg: UInt): Unit = this inPowerOf deg + public infix fun Int.of(deg: UInt): Unit = this inPowerOf deg } @NumberedPolynomialConstructorDSL @@ -168,6 +169,7 @@ public class NumberedPolynomialBuilderOverRing internal constructor(internal val signature = NumberedPolynomialTermSignatureBuilder().apply(block).build() coefficients[signature] = context { coefficients.getOrElse(signature) { zero } + this@invoke } } + public infix fun C.with(block: NumberedPolynomialTermSignatureBuilder.() -> Unit): Unit = this.invoke(block) } @NumberedPolynomialConstructorDSL -- 2.34.1 From f7286d33d27f9312f163106ef7f137cf594f1ff0 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Fri, 25 Mar 2022 17:18:56 +0300 Subject: [PATCH 065/275] Moved constructors to separate files. Replaced some TODOs with FIXMEs. --- .../kmath/functions/LabeledPolynomial.kt | 96 --------- .../functions/LabeledRationalFunction.kt | 33 --- .../kmath/functions/ListPolynomial.kt | 18 -- .../kmath/functions/ListRationalFunction.kt | 33 --- .../kmath/functions/NumberedPolynomial.kt | 148 +------------- .../functions/NumberedRationalFunction.kt | 33 --- .../kmath/functions/RationalFunction.kt | 9 +- .../kscience/kmath/functions/algebraicStub.kt | 16 +- .../kmath/functions/labeledConstructors.kt | 147 ++++++++++++++ .../kmath/functions/listConstructors.kt | 60 ++++++ .../kmath/functions/numberedConstructors.kt | 188 ++++++++++++++++++ .../kmath/functions/numberedPolynomialUtil.kt | 33 --- 12 files changed, 408 insertions(+), 406 deletions(-) create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt index 908e89534..b904f7331 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -8,10 +8,6 @@ package space.kscience.kmath.functions import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.ScaleOperations -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract -import kotlin.experimental.ExperimentalTypeInference -import kotlin.jvm.JvmName import kotlin.math.max @@ -49,98 +45,6 @@ internal constructor( override fun toString(): String = "LabeledPolynomial$coefficients" } -/** - * Returns the same degrees' description of the monomial, but without zero degrees. - */ -internal fun Map.cleanUp() = filterValues { it > 0U } - -// Waiting for context receivers :( TODO: Replace with context receivers when they will be available - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(coefs, toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(coefs, toCheckInput) -@Suppress("FunctionName") -internal fun > A.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial { - if (!toCheckInput) return LabeledPolynomial(coefs) - - val fixedCoefs = mutableMapOf, C>() - - for (entry in coefs) { - val key = entry.key.cleanUp() - val value = entry.value - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return LabeledPolynomial(fixedCoefs) -} - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs, toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs, toCheckInput) -@Suppress("FunctionName") -internal fun > A.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial { - if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) - - val fixedCoefs = mutableMapOf, C>() - - for (entry in pairs) { - val key = entry.first.cleanUp() - val value = entry.second - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return LabeledPolynomial(fixedCoefs) -} - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs = pairs, toCheckInput = toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs = pairs, toCheckInput = toCheckInput) -@Suppress("FunctionName") -internal fun > A.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial { - if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) - - val fixedCoefs = mutableMapOf, C>() - - for (entry in pairs) { - val key = entry.first.cleanUp() - val value = entry.second - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return LabeledPolynomial(fixedCoefs) -} - -@Suppress("FunctionName") -public fun > A.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledPolynomialSpace.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) - -@Suppress("FunctionName") -public fun > A.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledPolynomialSpace.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) - -@Suppress("FunctionName") -public fun > A.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledPolynomialSpace.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) - -//context(A) -//public fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to one)) -//context(LabeledPolynomialSpace) -//public fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to constantOne)) - -public fun C.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to this)) - /** * Space of polynomials. * diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt index 0f46520dc..76c6874f5 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt @@ -17,39 +17,6 @@ public class LabeledRationalFunction( override fun toString(): String = "LabeledRationalFunction${numerator.coefficients}/${denominator.coefficients}" } -// Waiting for context receivers :( TODO: Replace with context receivers when they will be available - -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): LabeledRationalFunction = - LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients, toCheckInput = true), - LabeledPolynomial(denominatorCoefficients, toCheckInput = true) - ) -@Suppress("FunctionName") -public fun > A.LabeledRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): LabeledRationalFunction = - LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients, toCheckInput = true), - LabeledPolynomial(denominatorCoefficients, toCheckInput = true) - ) -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numerator: LabeledPolynomial): LabeledRationalFunction = - LabeledRationalFunction(numerator, polynomialOne) -@Suppress("FunctionName") -public fun > A.LabeledRationalFunction(numerator: LabeledPolynomial): LabeledRationalFunction = - LabeledRationalFunction(numerator, LabeledPolynomial(mapOf(emptyMap() to one), toCheckInput = false)) -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numeratorCoefficients: Map, C>): LabeledRationalFunction = - LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients, toCheckInput = true), - polynomialOne - ) -@Suppress("FunctionName") -public fun > A.LabeledRationalFunction(numeratorCoefficients: Map, C>): LabeledRationalFunction = - LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients, toCheckInput = true), - LabeledPolynomial(mapOf(emptyMap() to one), toCheckInput = false) - ) - public class LabeledRationalFunctionSpace>( public val ring: A, ) : diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt index 711d2bb49..585da95ea 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt @@ -50,24 +50,6 @@ public data class ListPolynomial( override fun toString(): String = "Polynomial$coefficients" } -/** - * Returns a [ListPolynomial] instance with given [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 }) - -/** - * Returns a [ListPolynomial] instance with given [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() }) - -public fun C.asListPolynomial() : ListPolynomial = ListPolynomial(listOf(this)) - /** * Space of univariate polynomials constructed over ring. * diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt index f62d1857f..7b6c23ac3 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt @@ -15,39 +15,6 @@ public data class ListRationalFunction( override fun toString(): String = "RationalFunction${numerator.coefficients}/${denominator.coefficients}" } -// Waiting for context receivers :( TODO: Replace with context receivers when they will be available - -@Suppress("FunctionName") -public fun > ListRationalFunctionSpace.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 } ) - ) -@Suppress("FunctionName") -public fun > A.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 } ) - ) -@Suppress("FunctionName") -public fun > ListRationalFunctionSpace.ListRationalFunction(numerator: ListPolynomial): ListRationalFunction = - ListRationalFunction(numerator, polynomialOne) -@Suppress("FunctionName") -public fun > A.ListRationalFunction(numerator: ListPolynomial): ListRationalFunction = - ListRationalFunction(numerator, ListPolynomial(listOf(one))) -@Suppress("FunctionName") -public fun > ListRationalFunctionSpace.ListRationalFunction(numeratorCoefficients: List, reverse: Boolean = false): ListRationalFunction = - ListRationalFunction( - ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), - polynomialOne - ) -@Suppress("FunctionName") -public fun > A.ListRationalFunction(numeratorCoefficients: List, reverse: Boolean = false): ListRationalFunction = - ListRationalFunction( - ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), - ListPolynomial(listOf(one)) - ) - public class ListRationalFunctionSpace> ( public val ring: A, ) : diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index f931e8e7e..e75373819 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -49,152 +49,6 @@ internal constructor( override fun toString(): String = "NumberedPolynomial$coefficients" } -/** - * 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) - -// Waiting for context receivers :( TODO: Replace with context receivers when they will be available - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(coefs, toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(coefs, toCheckInput) -@Suppress("FunctionName") -internal fun > A.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial { - if (!toCheckInput) return NumberedPolynomial(coefs) - - val fixedCoefs = mutableMapOf, C>() - - for (entry in coefs) { - val key = entry.key.cleanUp() - val value = entry.value - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return NumberedPolynomial(fixedCoefs) -} - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs, toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs, toCheckInput) -@Suppress("FunctionName") -internal fun > A.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial { - if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) - - val fixedCoefs = mutableMapOf, C>() - - for (entry in pairs) { - val key = entry.first.cleanUp() - val value = entry.second - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return NumberedPolynomial(fixedCoefs) -} - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs = pairs, toCheckInput = toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs = pairs, toCheckInput = toCheckInput) -@Suppress("FunctionName") -internal fun > A.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial { - if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) - - val fixedCoefs = mutableMapOf, C>() - - for (entry in pairs) { - val key = entry.first.cleanUp() - val value = entry.second - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return NumberedPolynomial(fixedCoefs) -} - -@Suppress("FunctionName") -public fun > A.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedPolynomialSpace.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) - -@Suppress("FunctionName") -public fun > A.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedPolynomialSpace.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) - -@Suppress("FunctionName") -public fun > A.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedPolynomialSpace.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) - -//context(A) -//public fun > Symbol.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(mapOf(this to 1u) to one)) -//context(NumberedPolynomialSpace) -//public fun > Symbol.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(mapOf(this to 1u) to constantOne)) - -//context(A) -//public fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(emptyList() to this)) - -@DslMarker -internal annotation class NumberedPolynomialConstructorDSL - -@NumberedPolynomialConstructorDSL -public class NumberedPolynomialTermSignatureBuilder { - private val signature: MutableList = ArrayList() - public fun build(): List = signature - public infix fun Int.inPowerOf(deg: UInt) { - if (this > signature.lastIndex) { - signature.addAll(List(this - signature.lastIndex - 1) { 0u }) - signature.add(deg) - } else { - signature[this] = deg - } - } - public infix fun Int.pow(deg: UInt): Unit = this inPowerOf deg - public infix fun Int.of(deg: UInt): Unit = this inPowerOf deg -} - -@NumberedPolynomialConstructorDSL -public class NumberedPolynomialBuilderOverRing internal constructor(internal val context: Ring, capacity: Int = 0) { - private val coefficients: MutableMap, C> = LinkedHashMap(capacity) - public fun build(): NumberedPolynomial = NumberedPolynomial(coefficients) - public operator fun C.invoke(block: NumberedPolynomialTermSignatureBuilder.() -> Unit) { - val signature = NumberedPolynomialTermSignatureBuilder().apply(block).build() - coefficients[signature] = context { coefficients.getOrElse(signature) { zero } + this@invoke } - } - public infix fun C.with(block: NumberedPolynomialTermSignatureBuilder.() -> Unit): Unit = this.invoke(block) -} - -@NumberedPolynomialConstructorDSL -public class NumberedPolynomialBuilderOverPolynomialSpace internal constructor(internal val context: NumberedPolynomialSpace, capacity: Int = 0) { - private val coefficients: MutableMap, C> = LinkedHashMap(capacity) - public fun build(): NumberedPolynomial = NumberedPolynomial(coefficients) - public operator fun C.invoke(block: NumberedPolynomialTermSignatureBuilder.() -> Unit) { - val signature = NumberedPolynomialTermSignatureBuilder().apply(block).build() - coefficients[signature] = context { coefficients.getOrElse(signature) { constantZero } + this@invoke } - } -} - -@NumberedPolynomialConstructorDSL -@Suppress("FunctionName") -public fun > A.NumberedPolynomial(block: NumberedPolynomialBuilderOverRing.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilderOverRing(this).apply(block).build() -@NumberedPolynomialConstructorDSL -@Suppress("FunctionName") -public fun > A.NumberedPolynomial(capacity: Int, block: NumberedPolynomialBuilderOverRing.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilderOverRing(this, capacity).apply(block).build() -@NumberedPolynomialConstructorDSL -@Suppress("FunctionName") -public fun > NumberedPolynomialSpace.NumberedPolynomial(block: NumberedPolynomialBuilderOverPolynomialSpace.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilderOverPolynomialSpace(this).apply(block).build() -@NumberedPolynomialConstructorDSL -@Suppress("FunctionName") -public fun > NumberedPolynomialSpace.NumberedPolynomial(capacity: Int, block: NumberedPolynomialBuilderOverPolynomialSpace.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilderOverPolynomialSpace(this, capacity).apply(block).build() - /** * Space of polynomials. * @@ -530,6 +384,6 @@ public open class NumberedPolynomialSpace>( @JvmName("invokePolynomial") public inline operator fun NumberedPolynomial.invoke(argument: Map>): NumberedPolynomial = this.substitute(ring, argument) - // TODO: Move to other constructors with context receiver + // FIXME: Move to other constructors with context receiver public fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(emptyList() to this)) } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt index b4d9f1d91..30c7f0188 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt @@ -17,39 +17,6 @@ public class NumberedRationalFunction internal constructor( override fun toString(): String = "NumberedRationalFunction${numerator.coefficients}/${denominator.coefficients}" } -// Waiting for context receivers :( TODO: Replace with context receivers when they will be available - -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): NumberedRationalFunction = - NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients, toCheckInput = true), - NumberedPolynomial(denominatorCoefficients, toCheckInput = true) - ) -@Suppress("FunctionName") -public fun > A.NumberedRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): NumberedRationalFunction = - NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients, toCheckInput = true), - NumberedPolynomial(denominatorCoefficients, toCheckInput = true) - ) -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numerator: NumberedPolynomial): NumberedRationalFunction = - NumberedRationalFunction(numerator, polynomialOne) -@Suppress("FunctionName") -public fun > A.NumberedRationalFunction(numerator: NumberedPolynomial): NumberedRationalFunction = - NumberedRationalFunction(numerator, NumberedPolynomial(mapOf(emptyList() to one), toCheckInput = false)) -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numeratorCoefficients: Map, C>): NumberedRationalFunction = - NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients, toCheckInput = true), - polynomialOne - ) -@Suppress("FunctionName") -public fun > A.NumberedRationalFunction(numeratorCoefficients: Map, C>): NumberedRationalFunction = - NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients, toCheckInput = true), - NumberedPolynomial(mapOf(emptyList() to one), toCheckInput = false) - ) - public class NumberedRationalFunctionSpace> ( public val ring: A, ) : diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index 374f4a936..eede543ee 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -27,7 +27,7 @@ public interface RationalFunction> { * @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. - */ // TODO: Add support of field + */ @Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") public interface RationalFunctionalSpace, R: RationalFunction> : Ring { /** @@ -457,7 +457,7 @@ public interface RationalFunctionalSpace, R: RationalFunctio * @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. - */ // TODO: Add support of field + */ @Suppress("INAPPLICABLE_JVM_NAME") public interface RationalFunctionalSpaceOverRing, R: RationalFunction, A: Ring> : RationalFunctionalSpace { @@ -551,7 +551,7 @@ public interface RationalFunctionalSpaceOverRing, R: Rationa * @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. - */ // TODO: Add support of field + */ @Suppress("INAPPLICABLE_JVM_NAME") public interface RationalFunctionalSpaceOverPolynomialSpace< C, @@ -779,8 +779,7 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< * @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. - */ // TODO: Add support of field + */ @Suppress("INAPPLICABLE_JVM_NAME") public abstract class PolynomialSpaceOfFractions< C, diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt index ca93e4259..fa97d6a6c 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt @@ -9,7 +9,7 @@ import space.kscience.kmath.operations.* // TODO: All of this should be moved to algebraic structures' place for utilities -// TODO: Move receiver to context receiver +// FIXME: Move receiver to context receiver /** * Returns product of [arg] and integer [multiplier]. * @@ -22,7 +22,7 @@ internal fun Group.multiplyBySquaring(arg: C, multiplier: Int): C = if (multiplier >= 0) multiplyBySquaring(arg, multiplier.toUInt()) else multiplyBySquaring(-arg, (-multiplier).toUInt()) -// TODO: Move receiver to context receiver +// FIXME: Move receiver to context receiver /** * Adds product of [arg] and [multiplier] to [base]. * @@ -36,7 +36,7 @@ internal fun GroupOps.addMultipliedBySquaring(base: C, arg: C, multiplier if (multiplier >= 0) addMultipliedBySquaring(base, arg, multiplier.toUInt()) else addMultipliedBySquaring(base, -arg, (-multiplier).toUInt()) -// TODO: Move receiver to context receiver +// FIXME: Move receiver to context receiver /** * Returns product of [arg] and integer [multiplier]. * @@ -56,7 +56,7 @@ internal tailrec fun Group.multiplyBySquaring(arg: C, multiplier: UInt): else -> error("Error in multiplication group instant by unsigned integer: got reminder by division by 2 different from 0 and 1") } -// TODO: Move receiver to context receiver +// FIXME: Move receiver to context receiver /** * Adds product of [arg] and [multiplier] to [base]. * @@ -77,7 +77,7 @@ internal tailrec fun GroupOps.addMultipliedBySquaring(base: C, arg: C, mu else -> error("Error in multiplication group instant by unsigned integer: got reminder by division by 2 different from 0 and 1") } -// TODO: Move receiver to context receiver +// FIXME: Move receiver to context receiver /** * Raises [arg] to the integer power [exponent]. * @@ -90,7 +90,7 @@ internal fun Field.exponentiationBySquaring(arg: C, exponent: Int): C = if (exponent >= 0) exponentiationBySquaring(arg, exponent.toUInt()) else exponentiationBySquaring(one / arg, (-exponent).toUInt()) -// TODO: Move receiver to context receiver +// FIXME: Move receiver to context receiver /** * Multiplies [base] and [arg] raised to the integer power [exponent]. * @@ -104,7 +104,7 @@ internal fun Field.multiplyExponentiationBySquaring(base: C, arg: C, expo if (exponent >= 0) multiplyExponentiationBySquaring(base, arg, exponent.toUInt()) else multiplyExponentiationBySquaring(base, one / arg, (-exponent).toUInt()) -// TODO: Move receiver to context receiver +// FIXME: Move receiver to context receiver /** * Raises [arg] to the integer power [exponent]. * @@ -124,7 +124,7 @@ internal tailrec fun Ring.exponentiationBySquaring(arg: C, exponent: UInt else -> error("Error in multiplication group instant by unsigned integer: got reminder by division by 2 different from 0 and 1") } -// TODO: Move receiver to context receiver +// FIXME: Move receiver to context receiver /** * Multiplies [base] and [arg] raised to the integer power [exponent]. * diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt new file mode 100644 index 000000000..12688a865 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt @@ -0,0 +1,147 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.operations.Ring + + +/** + * Returns the same degrees' description of the monomial, but without zero degrees. + */ +internal fun Map.cleanUp() = filterValues { it > 0U } + +// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available + +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(coefs, toCheckInput) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(coefs, toCheckInput) +@Suppress("FunctionName") +internal fun > A.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial { + if (!toCheckInput) return LabeledPolynomial(coefs) + + val fixedCoefs = LinkedHashMap, C>(coefs.size) + + for (entry in coefs) { + val key = entry.key.cleanUp() + val value = entry.value + fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value + } + + return LabeledPolynomial(fixedCoefs) +} + +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs, toCheckInput) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs, toCheckInput) +@Suppress("FunctionName") +internal fun > A.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial { + if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) + + val fixedCoefs = LinkedHashMap, C>(pairs.size) + + for (entry in pairs) { + val key = entry.first.cleanUp() + val value = entry.second + fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value + } + + return LabeledPolynomial(fixedCoefs) +} + +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs = pairs, toCheckInput = toCheckInput) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs = pairs, toCheckInput = toCheckInput) +@Suppress("FunctionName") +internal fun > A.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial { + if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) + + val fixedCoefs = LinkedHashMap, C>(pairs.size) + + for (entry in pairs) { + val key = entry.first.cleanUp() + val value = entry.second + fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value + } + + return LabeledPolynomial(fixedCoefs) +} + +@Suppress("FunctionName") +public fun > A.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) +@Suppress("FunctionName") +public fun > LabeledPolynomialSpace.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) +@Suppress("FunctionName") +public fun > LabeledRationalFunctionSpace.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) + +@Suppress("FunctionName") +public fun > A.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > LabeledPolynomialSpace.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > LabeledRationalFunctionSpace.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) + +@Suppress("FunctionName") +public fun > A.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > LabeledPolynomialSpace.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > LabeledRationalFunctionSpace.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) + +//context(A) +//public fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to one)) +//context(LabeledPolynomialSpace) +//public fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to constantOne)) +//context(LabeledRationalFunctionSpace) +//public fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to constantOne)) + +public fun C.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to this)) + +// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available + +@Suppress("FunctionName") +public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): LabeledRationalFunction = + LabeledRationalFunction( + LabeledPolynomial(numeratorCoefficients, toCheckInput = true), + LabeledPolynomial(denominatorCoefficients, toCheckInput = true) + ) +@Suppress("FunctionName") +public fun > A.LabeledRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): LabeledRationalFunction = + LabeledRationalFunction( + LabeledPolynomial(numeratorCoefficients, toCheckInput = true), + LabeledPolynomial(denominatorCoefficients, toCheckInput = true) + ) +@Suppress("FunctionName") +public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numerator: LabeledPolynomial): LabeledRationalFunction = + LabeledRationalFunction(numerator, polynomialOne) +@Suppress("FunctionName") +public fun > A.LabeledRationalFunction(numerator: LabeledPolynomial): LabeledRationalFunction = + LabeledRationalFunction(numerator, LabeledPolynomial(mapOf(emptyMap() to one), toCheckInput = false)) +@Suppress("FunctionName") +public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numeratorCoefficients: Map, C>): LabeledRationalFunction = + LabeledRationalFunction( + LabeledPolynomial(numeratorCoefficients, toCheckInput = true), + polynomialOne + ) +@Suppress("FunctionName") +public fun > A.LabeledRationalFunction(numeratorCoefficients: Map, C>): LabeledRationalFunction = + LabeledRationalFunction( + LabeledPolynomial(numeratorCoefficients, toCheckInput = true), + LabeledPolynomial(mapOf(emptyMap() to one), toCheckInput = false) + ) + +//context(A) +//public fun > Symbol.asLabeledRationalFunction() : LabeledRationalFunction = LabeledRationalFunction(asLabeledPolynomial()) +//context(LabeledRationalFunctionSpace) +//public fun > Symbol.asLabeledRationalFunction() : LabeledRationalFunction = LabeledRationalFunction(asLabeledPolynomial()) + +//context(A) +//public fun > C.asLabeledRationalFunction() : LabeledRationalFunction = LabeledRationalFunction(asLabeledPolynomial()) +//context(LabeledRationalFunctionSpace) +//public fun > C.asLabeledRationalFunction() : LabeledRationalFunction = LabeledRationalFunction(asLabeledPolynomial()) \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt new file mode 100644 index 000000000..9498c77ca --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.Ring + + +/** + * Returns a [ListPolynomial] instance with given [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 }) + +/** + * Returns a [ListPolynomial] instance with given [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() }) + +public fun C.asListPolynomial() : ListPolynomial = ListPolynomial(listOf(this)) + + +// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available + +@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 } ) + ) +@Suppress("FunctionName") +public fun > ListRationalFunctionSpace.ListRationalFunction(numerator: ListPolynomial): ListRationalFunction = + ListRationalFunction(numerator, polynomialOne) +@Suppress("FunctionName") +public fun > A.ListRationalFunction(numerator: ListPolynomial): ListRationalFunction = + ListRationalFunction(numerator, ListPolynomial(listOf(one))) +@Suppress("FunctionName") +public fun > ListRationalFunctionSpace.ListRationalFunction(numeratorCoefficients: List, reverse: Boolean = false): ListRationalFunction = + ListRationalFunction( + ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), + polynomialOne + ) +@Suppress("FunctionName") +public fun > A.ListRationalFunction(numeratorCoefficients: List, reverse: Boolean = false): ListRationalFunction = + ListRationalFunction( + ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), + ListPolynomial(listOf(one)) + ) + +//context(A) +//public fun > C.asListRationalFunction() : ListRationalFunction = ListRationalFunction(asListPolynomial()) +//context(ListRationalFunctionSpace) +//public fun > C.asListRationalFunction() : ListRationalFunction = ListRationalFunction(asListPolynomial()) \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt new file mode 100644 index 000000000..e4b79b0b2 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt @@ -0,0 +1,188 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.invoke + + +/** + * 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) + +// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available + +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(coefs, toCheckInput) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(coefs, toCheckInput) +@Suppress("FunctionName") +internal fun > A.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial { + if (!toCheckInput) return NumberedPolynomial(coefs) + + val fixedCoefs = mutableMapOf, C>() + + for (entry in coefs) { + val key = entry.key.cleanUp() + val value = entry.value + fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value + } + + return NumberedPolynomial(fixedCoefs) +} + +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs, toCheckInput) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs, toCheckInput) +@Suppress("FunctionName") +internal fun > A.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial { + if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) + + val fixedCoefs = mutableMapOf, C>() + + for (entry in pairs) { + val key = entry.first.cleanUp() + val value = entry.second + fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value + } + + return NumberedPolynomial(fixedCoefs) +} + +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs = pairs, toCheckInput = toCheckInput) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs = pairs, toCheckInput = toCheckInput) +@Suppress("FunctionName") +internal fun > A.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial { + if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) + + val fixedCoefs = mutableMapOf, C>() + + for (entry in pairs) { + val key = entry.first.cleanUp() + val value = entry.second + fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value + } + + return NumberedPolynomial(fixedCoefs) +} + +@Suppress("FunctionName") +public fun > A.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) +@Suppress("FunctionName") +public fun > NumberedPolynomialSpace.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) +@Suppress("FunctionName") +public fun > NumberedRationalFunctionSpace.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) + +@Suppress("FunctionName") +public fun > A.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > NumberedPolynomialSpace.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > NumberedRationalFunctionSpace.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) + +@Suppress("FunctionName") +public fun > A.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > NumberedPolynomialSpace.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > NumberedRationalFunctionSpace.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) + +public fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(emptyList() to this)) + +@DslMarker +internal annotation class NumberedPolynomialConstructorDSL + +@NumberedPolynomialConstructorDSL +public class NumberedPolynomialTermSignatureBuilder { + private val signature: MutableList = ArrayList() + public fun build(): List = signature + public infix fun Int.inPowerOf(deg: UInt) { + if (this > signature.lastIndex) { + signature.addAll(List(this - signature.lastIndex - 1) { 0u }) + signature.add(deg) + } else { + signature[this] = deg + } + } + public infix fun Int.pow(deg: UInt): Unit = this inPowerOf deg + public infix fun Int.of(deg: UInt): Unit = this inPowerOf deg +} + +@NumberedPolynomialConstructorDSL +public class NumberedPolynomialBuilderOverRing internal constructor(internal val context: Ring, capacity: Int = 0) { + private val coefficients: MutableMap, C> = LinkedHashMap(capacity) + public fun build(): NumberedPolynomial = NumberedPolynomial(coefficients) + public operator fun C.invoke(block: NumberedPolynomialTermSignatureBuilder.() -> Unit) { + val signature = NumberedPolynomialTermSignatureBuilder().apply(block).build() + coefficients[signature] = context { coefficients.getOrElse(signature) { zero } + this@invoke } + } + public infix fun C.with(block: NumberedPolynomialTermSignatureBuilder.() -> Unit): Unit = this.invoke(block) +} + +@NumberedPolynomialConstructorDSL +public class NumberedPolynomialBuilderOverPolynomialSpace internal constructor(internal val context: NumberedPolynomialSpace, capacity: Int = 0) { + private val coefficients: MutableMap, C> = LinkedHashMap(capacity) + public fun build(): NumberedPolynomial = NumberedPolynomial(coefficients) + public operator fun C.invoke(block: NumberedPolynomialTermSignatureBuilder.() -> Unit) { + val signature = NumberedPolynomialTermSignatureBuilder().apply(block).build() + coefficients[signature] = context { coefficients.getOrElse(signature) { constantZero } + this@invoke } + } +} + +@NumberedPolynomialConstructorDSL +@Suppress("FunctionName") +public fun > A.NumberedPolynomial(block: NumberedPolynomialBuilderOverRing.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilderOverRing(this).apply(block).build() +@NumberedPolynomialConstructorDSL +@Suppress("FunctionName") +public fun > A.NumberedPolynomial(capacity: Int, block: NumberedPolynomialBuilderOverRing.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilderOverRing(this, capacity).apply(block).build() +@NumberedPolynomialConstructorDSL +@Suppress("FunctionName") +public fun > NumberedPolynomialSpace.NumberedPolynomial(block: NumberedPolynomialBuilderOverPolynomialSpace.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilderOverPolynomialSpace(this).apply(block).build() +@NumberedPolynomialConstructorDSL +@Suppress("FunctionName") +public fun > NumberedPolynomialSpace.NumberedPolynomial(capacity: Int, block: NumberedPolynomialBuilderOverPolynomialSpace.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilderOverPolynomialSpace(this, capacity).apply(block).build() + +// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available + +@Suppress("FunctionName") +public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): NumberedRationalFunction = + NumberedRationalFunction( + NumberedPolynomial(numeratorCoefficients, toCheckInput = true), + NumberedPolynomial(denominatorCoefficients, toCheckInput = true) + ) +@Suppress("FunctionName") +public fun > A.NumberedRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): NumberedRationalFunction = + NumberedRationalFunction( + NumberedPolynomial(numeratorCoefficients, toCheckInput = true), + NumberedPolynomial(denominatorCoefficients, toCheckInput = true) + ) +@Suppress("FunctionName") +public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numerator: NumberedPolynomial): NumberedRationalFunction = + NumberedRationalFunction(numerator, polynomialOne) +@Suppress("FunctionName") +public fun > A.NumberedRationalFunction(numerator: NumberedPolynomial): NumberedRationalFunction = + NumberedRationalFunction(numerator, NumberedPolynomial(mapOf(emptyList() to one), toCheckInput = false)) +@Suppress("FunctionName") +public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numeratorCoefficients: Map, C>): NumberedRationalFunction = + NumberedRationalFunction( + NumberedPolynomial(numeratorCoefficients, toCheckInput = true), + polynomialOne + ) +@Suppress("FunctionName") +public fun > A.NumberedRationalFunction(numeratorCoefficients: Map, C>): NumberedRationalFunction = + NumberedRationalFunction( + NumberedPolynomial(numeratorCoefficients, toCheckInput = true), + NumberedPolynomial(mapOf(emptyList() to one), toCheckInput = false) + ) + +//context(A) +//public fun > C.asNumberedRationalFunction() : NumberedRationalFunction = NumberedRationalFunction(asLabeledPolynomial()) +//context(NumberedRationalFunctionSpace) +//public fun > C.asNumberedRationalFunction() : NumberedRationalFunction = NumberedRationalFunction(asLabeledPolynomial()) \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt index d544ca93c..ee85b0f56 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt @@ -9,38 +9,6 @@ import kotlin.math.max // TODO: Docs -//// TODO: Reuse underlying ring extensions -// -//context(NumberedPolynomialSpace) -//@Suppress("NOTHING_TO_INLINE") -//public fun > numberConstant(value: Int): C = ring { number(value) } -// -//context(NumberedPolynomialSpace) -//public fun > multiplyWithPower(base: C, arg: C, pow: UInt): C = ring { multiplyWithPower(base, arg, pow) } - -//context(NumberedPolynomialSpace) -//public fun > number(value: Int): NumberedPolynomial = ring { NumberedPolynomial(mapOf(emptyList() to number(value))) } -// -//context(NumberedPolynomialSpace) -//public fun > multiplyWithPower(base: NumberedPolynomial, arg: NumberedPolynomial, pow: UInt): NumberedPolynomial = -// when { -// arg.isZero() && pow > 0U -> base -// arg.isOne() -> base -// arg.isMinusOne() -> if (pow % 2U == 0U) base else -base -// else -> multiplyWithPowerInternalLogic(base, arg, pow) -// } -// -//// Trivial but very slow -//context(NumberedPolynomialSpace) -//internal tailrec fun > multiplyWithPowerInternalLogic(base: NumberedPolynomial, arg: NumberedPolynomial, exponent: UInt): NumberedPolynomial = -// when { -// exponent == 0U -> base -// exponent == 1U -> base * arg -// exponent % 2U == 0U -> multiplyWithPowerInternalLogic(base, arg * arg, exponent / 2U) -// exponent % 2U == 1U -> multiplyWithPowerInternalLogic(base * arg, arg * arg, exponent / 2U) -// else -> error("Error in raising ring instant by unsigned integer: got reminder by division by 2 different from 0 and 1") -// } - /** * Creates a [NumberedPolynomialSpace] over a received ring. */ @@ -271,7 +239,6 @@ public inline fun , R> A.numberedPolynomial(block: NumberedPolyno // toCheckInput = false // ) -// TODO: May be apply Horner's method too? /** * Evaluates the value of the given double polynomial for given double argument. */ -- 2.34.1 From b3087c245fc0da2631e9e53211e97dd47e1d1983 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Fri, 25 Mar 2022 17:46:13 +0300 Subject: [PATCH 066/275] Fixed tests. --- .../kmath/functions/ListPolynomialTest.kt | 108 ++++-------------- .../kmath/functions/ListPolynomialUtilTest.kt | 16 +-- .../kscience/kmath/test/misc/IntModulo.kt | 2 +- 3 files changed, 33 insertions(+), 93 deletions(-) diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt index ac2647592..5401be707 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt @@ -9,7 +9,7 @@ import space.kscience.kmath.test.misc.* import kotlin.test.* -class ListPolynomialTest { // TODO: Adapt tests to changes +class ListPolynomialTest { @Test fun test_Polynomial_Int_plus() { RationalField.listPolynomial { @@ -24,7 +24,7 @@ class ListPolynomialTest { // TODO: Adapt tests to changes "test 2" ) assertEquals( - ListPolynomial(), + ListPolynomial(Rational(0)), ListPolynomial(Rational(-2)) + 2, "test 3" ) @@ -64,7 +64,7 @@ class ListPolynomialTest { // TODO: Adapt tests to changes "test 2" ) assertEquals( - ListPolynomial(), + ListPolynomial(Rational(0)), ListPolynomial(Rational(2)) - 2, "test 3" ) @@ -99,7 +99,7 @@ class ListPolynomialTest { // TODO: Adapt tests to changes "test 1" ) assertEquals( - ListPolynomial(), + ListPolynomial(0, 0, 0, 0, 0), ListPolynomial(7, 0, 49, 21, 14) * 15, "test 2" ) @@ -119,7 +119,7 @@ class ListPolynomialTest { // TODO: Adapt tests to changes "test 2" ) assertEquals( - ListPolynomial(), + ListPolynomial(Rational(0)), 2 + ListPolynomial(Rational(-2)), "test 3" ) @@ -159,7 +159,7 @@ class ListPolynomialTest { // TODO: Adapt tests to changes "test 2" ) assertEquals( - ListPolynomial(), + ListPolynomial(Rational(0)), -2 - ListPolynomial(Rational(-2)), "test 3" ) @@ -194,7 +194,7 @@ class ListPolynomialTest { // TODO: Adapt tests to changes "test 1" ) assertEquals( - ListPolynomial(), + ListPolynomial(0, 0, 0, 0, 0), 15 * ListPolynomial(7, 0, 49, 21, 14), "test 2" ) @@ -214,12 +214,12 @@ class ListPolynomialTest { // TODO: Adapt tests to changes "test 2" ) assertEquals( - ListPolynomial(), + ListPolynomial(Rational(0)), ListPolynomial(Rational(-2)) + Rational(2), "test 3" ) assertEquals( - ListPolynomial(), + ListPolynomial(Rational(0)), ListPolynomial() + Rational(0), "test 4" ) @@ -254,12 +254,12 @@ class ListPolynomialTest { // TODO: Adapt tests to changes "test 2" ) assertEquals( - ListPolynomial(), + ListPolynomial(Rational(0)), ListPolynomial(Rational(2)) - Rational(2), "test 3" ) assertEquals( - ListPolynomial(), + ListPolynomial(Rational(0)), ListPolynomial() - Rational(0), "test 4" ) @@ -285,12 +285,12 @@ class ListPolynomialTest { // TODO: Adapt tests to changes IntModuloRing(35).listPolynomial { assertEquals( ListPolynomial(34, 2, 1, 20, 2), - ListPolynomial(22, 26, 13, 15, 26) * number(27), + ListPolynomial(22, 26, 13, 15, 26) * 27.asConstant(), "test 1" ) assertEquals( - ListPolynomial(), - ListPolynomial(7, 0, 49, 21, 14) * number(15), + ListPolynomial(0, 0, 0, 0, 0), + ListPolynomial(7, 0, 49, 21, 14) * 15.asConstant(), "test 2" ) } @@ -309,12 +309,12 @@ class ListPolynomialTest { // TODO: Adapt tests to changes "test 2" ) assertEquals( - ListPolynomial(), + ListPolynomial(Rational(0)), Rational(2) + ListPolynomial(Rational(-2)), "test 3" ) assertEquals( - ListPolynomial(), + ListPolynomial(Rational(0)), Rational(0) + ListPolynomial(), "test 4" ) @@ -349,12 +349,12 @@ class ListPolynomialTest { // TODO: Adapt tests to changes "test 2" ) assertEquals( - ListPolynomial(), + ListPolynomial(Rational(0)), Rational(-2) - ListPolynomial(Rational(-2)), "test 3" ) assertEquals( - ListPolynomial(), + ListPolynomial(Rational(0)), Rational(0) - ListPolynomial(), "test 4" ) @@ -384,7 +384,7 @@ class ListPolynomialTest { // TODO: Adapt tests to changes "test 1" ) assertEquals( - ListPolynomial(), + ListPolynomial(0, 0, 0, 0, 0), 15 * ListPolynomial(7, 0, 49, 21, 14), "test 2" ) @@ -424,14 +424,14 @@ class ListPolynomialTest { // TODO: Adapt tests to changes ) // (-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)), + 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(), + 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" @@ -457,14 +457,14 @@ class ListPolynomialTest { // TODO: Adapt tests to changes ) // (-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)), + 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(), + 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" @@ -482,70 +482,10 @@ class ListPolynomialTest { // TODO: Adapt tests to changes ) // Spoiler: 5 * 7 = 0 assertEquals( - ListPolynomial(), + ListPolynomial(0, 0, 0, 0, 0), ListPolynomial(5, -25, 10) * ListPolynomial(21, 14, -7), "test 2" ) } } - @Test - fun test_Polynomial_degree() { - RationalField.listPolynomial { - assertEquals( - 2, - ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)).degree, - "test 1" - ) - assertEquals( - -1, - ListPolynomial().degree, - "test 2" - ) - assertEquals( - -1, - ListPolynomial(Rational(0)).degree, - "test 3" - ) - assertEquals( - -1, - ListPolynomial(Rational(0), Rational(0)).degree, - "test 4" - ) - assertEquals( - -1, - ListPolynomial(Rational(0), Rational(0), Rational(0)).degree, - "test 5" - ) - assertEquals( - 0, - ListPolynomial(Rational(5, 9)).degree, - "test 6" - ) - assertEquals( - 0, - ListPolynomial(Rational(5, 9), Rational(0)).degree, - "test 7" - ) - assertEquals( - 0, - ListPolynomial(Rational(5, 9), Rational(0), Rational(0)).degree, - "test 8" - ) - assertEquals( - 2, - ListPolynomial(Rational(0), Rational(0), Rational(-8, 7)).degree, - "test 9" - ) - assertEquals( - 2, - ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7), Rational(0), Rational(0)).degree, - "test 10" - ) - assertEquals( - 2, - ListPolynomial(Rational(0), Rational(0), Rational(-8, 7), Rational(0), Rational(0)).degree, - "test 11" - ) - } - } } \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt index c4f07d957..c5eb8fb81 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt @@ -12,7 +12,7 @@ import kotlin.test.assertEquals import kotlin.test.assertFailsWith -class ListPolynomialUtilTest { // TODO: Adapt tests to changes +class ListPolynomialUtilTest { @Test fun test_substitute_Double() { assertEquals( @@ -81,7 +81,7 @@ class ListPolynomialUtilTest { // TODO: Adapt tests to changes @Test fun test_substitute_Polynomial() { assertEquals( - ListPolynomial(), + ListPolynomial(Rational(0)), ListPolynomial(Rational(1), Rational(-2), Rational(1)).substitute(RationalField, ListPolynomial(Rational(1))), "test 1" ) @@ -98,7 +98,7 @@ class ListPolynomialUtilTest { // TODO: Adapt tests to changes "test 3" ) assertEquals( - ListPolynomial(Rational(677, 378), Rational(97, 180), Rational(1, 75)), + 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" @@ -110,7 +110,7 @@ class ListPolynomialUtilTest { // TODO: Adapt tests to changes "test 5" ) assertEquals( - ListPolynomial(Rational(89, 54)), + 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" @@ -134,7 +134,7 @@ class ListPolynomialUtilTest { // TODO: Adapt tests to changes "test 3" ) assertEquals( - ListPolynomial(Rational(-8, 3), Rational(8, 9), Rational(15, 7)), + 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" ) @@ -180,7 +180,7 @@ class ListPolynomialUtilTest { // TODO: Adapt tests to changes "test 8" ) assertEquals( - ListPolynomial(Rational(8, 9), Rational(30, 7)), + 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" ) @@ -203,7 +203,7 @@ class ListPolynomialUtilTest { // TODO: Adapt tests to changes "test 3" ) assertEquals( - ListPolynomial(Rational(0), Rational(1, 5), Rational(-4, 3), Rational(4, 27), Rational(5, 28)), + 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" ) @@ -249,7 +249,7 @@ class ListPolynomialUtilTest { // TODO: Adapt tests to changes "test 8" ) assertEquals( - ListPolynomial(Rational(0), Rational(0), Rational(1, 10), Rational(-4, 9), Rational(1, 27), Rational(1, 28)), + 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" ) diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt index 535a42846..2353beee6 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt @@ -120,7 +120,7 @@ class IntModuloRing : Ring { } override inline val zero: IntModulo get() = IntModulo(0, modulus, toCheckInput = false) - override inline val one: IntModulo get() = IntModulo(0, modulus, toCheckInput = false) + override inline val one: IntModulo get() = IntModulo(1, modulus, toCheckInput = false) fun number(arg: Int) = IntModulo(arg, modulus, toCheckInput = false) -- 2.34.1 From 7f7b55067422589bc9266f2d7ebc0e8af5b8e402 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sun, 3 Apr 2022 11:44:42 +0300 Subject: [PATCH 067/275] Simplified polynomial builders. --- .../kmath/functions/labeledConstructors.kt | 56 +++++++++++++++++++ .../kmath/functions/numberedConstructors.kt | 47 +++++++++------- 2 files changed, 83 insertions(+), 20 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt index 12688a865..e81a9388e 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt @@ -6,6 +6,7 @@ package space.kscience.kmath.functions import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Ring @@ -103,6 +104,61 @@ public fun > LabeledRationalFunctionSpace.LabeledPolynomial( public fun C.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to this)) +@DslMarker +@UnstableKMathAPI +internal annotation class LabeledPolynomialConstructorDSL + +@UnstableKMathAPI +@LabeledPolynomialConstructorDSL +public class LabeledPolynomialTermSignatureBuilder { + private val signature: MutableMap = LinkedHashMap() + public fun build(): Map = signature + public infix fun Symbol.inPowerOf(deg: UInt) { + signature[this] = deg + } + @Suppress("NOTHING_TO_INLINE") + public inline infix fun Symbol.pow(deg: UInt): Unit = this inPowerOf deg + @Suppress("NOTHING_TO_INLINE") + public inline infix fun Symbol.`in`(deg: UInt): Unit = this inPowerOf deg + @Suppress("NOTHING_TO_INLINE") + public inline infix fun Symbol.of(deg: UInt): Unit = this inPowerOf deg +} + +@UnstableKMathAPI +public class LabeledPolynomialBuilder(private val zero: C, private val add: (C, C) -> C, capacity: Int = 0) { + private val coefficients: MutableMap, C> = LinkedHashMap(capacity) + public fun build(): LabeledPolynomial = LabeledPolynomial(coefficients) + public operator fun C.invoke(block: LabeledPolynomialTermSignatureBuilder.() -> Unit) { + val signature = LabeledPolynomialTermSignatureBuilder().apply(block).build() + coefficients[signature] = add(coefficients.getOrElse(signature) { zero }, this@invoke) + } + @Suppress("NOTHING_TO_INLINE") + public inline infix fun C.with(noinline block: LabeledPolynomialTermSignatureBuilder.() -> Unit): Unit = this.invoke(block) + @Suppress("NOTHING_TO_INLINE") + public inline infix fun (LabeledPolynomialTermSignatureBuilder.() -> Unit).with(coef: C): Unit = coef.invoke(this) + @Suppress("NOTHING_TO_INLINE") + public infix fun sig(block: LabeledPolynomialTermSignatureBuilder.() -> Unit): LabeledPolynomialTermSignatureBuilder.() -> Unit = block +} + +// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available + +@UnstableKMathAPI +@LabeledPolynomialConstructorDSL +@Suppress("FunctionName") +public inline fun > A.LabeledPolynomial(block: LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = LabeledPolynomialBuilder(zero, ::add).apply(block).build() +@UnstableKMathAPI +@LabeledPolynomialConstructorDSL +@Suppress("FunctionName") +public inline fun > A.LabeledPolynomial(capacity: Int, block: LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = LabeledPolynomialBuilder(zero, ::add, capacity).apply(block).build() +@UnstableKMathAPI +@LabeledPolynomialConstructorDSL +@Suppress("FunctionName") +public inline fun > LabeledPolynomialSpace.LabeledPolynomial(block: LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = LabeledPolynomialBuilder(constantZero, { left: C, right: C -> left + right}).apply(block).build() +@UnstableKMathAPI +@LabeledPolynomialConstructorDSL +@Suppress("FunctionName") +public inline fun > LabeledPolynomialSpace.LabeledPolynomial(capacity: Int, block: LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = LabeledPolynomialBuilder(constantZero, { left: C, right: C -> left + right}, capacity).apply(block).build() + // Waiting for context receivers :( FIXME: Replace with context receivers when they will be available @Suppress("FunctionName") diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt index e4b79b0b2..dca8a0cff 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt @@ -5,8 +5,8 @@ package space.kscience.kmath.functions +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.invoke /** @@ -97,8 +97,10 @@ public fun > NumberedRationalFunctionSpace.NumberedPolynomia public fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(emptyList() to this)) @DslMarker +@UnstableKMathAPI internal annotation class NumberedPolynomialConstructorDSL +@UnstableKMathAPI @NumberedPolynomialConstructorDSL public class NumberedPolynomialTermSignatureBuilder { private val signature: MutableList = ArrayList() @@ -111,43 +113,48 @@ public class NumberedPolynomialTermSignatureBuilder { signature[this] = deg } } - public infix fun Int.pow(deg: UInt): Unit = this inPowerOf deg - public infix fun Int.of(deg: UInt): Unit = this inPowerOf deg + @Suppress("NOTHING_TO_INLINE") + public inline infix fun Int.pow(deg: UInt): Unit = this inPowerOf deg + @Suppress("NOTHING_TO_INLINE") + public inline infix fun Int.`in`(deg: UInt): Unit = this inPowerOf deg + @Suppress("NOTHING_TO_INLINE") + public inline infix fun Int.of(deg: UInt): Unit = this inPowerOf deg } -@NumberedPolynomialConstructorDSL -public class NumberedPolynomialBuilderOverRing internal constructor(internal val context: Ring, capacity: Int = 0) { +@UnstableKMathAPI +public class NumberedPolynomialBuilder(private val zero: C, private val add: (C, C) -> C, capacity: Int = 0) { private val coefficients: MutableMap, C> = LinkedHashMap(capacity) public fun build(): NumberedPolynomial = NumberedPolynomial(coefficients) public operator fun C.invoke(block: NumberedPolynomialTermSignatureBuilder.() -> Unit) { val signature = NumberedPolynomialTermSignatureBuilder().apply(block).build() - coefficients[signature] = context { coefficients.getOrElse(signature) { zero } + this@invoke } + coefficients[signature] = add(coefficients.getOrElse(signature) { zero }, this@invoke) } - public infix fun C.with(block: NumberedPolynomialTermSignatureBuilder.() -> Unit): Unit = this.invoke(block) + @Suppress("NOTHING_TO_INLINE") + public inline infix fun C.with(noinline block: NumberedPolynomialTermSignatureBuilder.() -> Unit): Unit = this.invoke(block) + @Suppress("NOTHING_TO_INLINE") + public inline infix fun (NumberedPolynomialTermSignatureBuilder.() -> Unit).with(coef: C): Unit = coef.invoke(this) + @Suppress("NOTHING_TO_INLINE") + public infix fun sig(block: NumberedPolynomialTermSignatureBuilder.() -> Unit): NumberedPolynomialTermSignatureBuilder.() -> Unit = block } -@NumberedPolynomialConstructorDSL -public class NumberedPolynomialBuilderOverPolynomialSpace internal constructor(internal val context: NumberedPolynomialSpace, capacity: Int = 0) { - private val coefficients: MutableMap, C> = LinkedHashMap(capacity) - public fun build(): NumberedPolynomial = NumberedPolynomial(coefficients) - public operator fun C.invoke(block: NumberedPolynomialTermSignatureBuilder.() -> Unit) { - val signature = NumberedPolynomialTermSignatureBuilder().apply(block).build() - coefficients[signature] = context { coefficients.getOrElse(signature) { constantZero } + this@invoke } - } -} +// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available +@UnstableKMathAPI @NumberedPolynomialConstructorDSL @Suppress("FunctionName") -public fun > A.NumberedPolynomial(block: NumberedPolynomialBuilderOverRing.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilderOverRing(this).apply(block).build() +public inline fun > A.NumberedPolynomial(block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder(zero, ::add).apply(block).build() +@UnstableKMathAPI @NumberedPolynomialConstructorDSL @Suppress("FunctionName") -public fun > A.NumberedPolynomial(capacity: Int, block: NumberedPolynomialBuilderOverRing.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilderOverRing(this, capacity).apply(block).build() +public inline fun > A.NumberedPolynomial(capacity: Int, block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder(zero, ::add, capacity).apply(block).build() +@UnstableKMathAPI @NumberedPolynomialConstructorDSL @Suppress("FunctionName") -public fun > NumberedPolynomialSpace.NumberedPolynomial(block: NumberedPolynomialBuilderOverPolynomialSpace.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilderOverPolynomialSpace(this).apply(block).build() +public inline fun > NumberedPolynomialSpace.NumberedPolynomial(block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder(constantZero, { left: C, right: C -> left + right}).apply(block).build() +@UnstableKMathAPI @NumberedPolynomialConstructorDSL @Suppress("FunctionName") -public fun > NumberedPolynomialSpace.NumberedPolynomial(capacity: Int, block: NumberedPolynomialBuilderOverPolynomialSpace.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilderOverPolynomialSpace(this, capacity).apply(block).build() +public inline fun > NumberedPolynomialSpace.NumberedPolynomial(capacity: Int, block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder(constantZero, { left: C, right: C -> left + right}, capacity).apply(block).build() // Waiting for context receivers :( FIXME: Replace with context receivers when they will be available -- 2.34.1 From 5a36c3e03c60ffe02b7e7ea5609843b6f3a4155d Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 13 Apr 2022 11:20:11 +0300 Subject: [PATCH 068/275] Remove metaspace memory allocation key --- gradle.properties | 1 - 1 file changed, 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 80108737e..4923364d8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,5 +9,4 @@ kotlin.native.ignoreDisabledTargets=true #kotlin.incremental.js.ir=true org.gradle.configureondemand=true -org.gradle.jvmargs=-XX:MaxMetaspaceSize=1G org.gradle.parallel=true -- 2.34.1 From 2ddf9fcd4e81a2e4f5e768b4be88bbe02f66b85b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Willi=20Sch=C3=B6nborn?= Date: Tue, 19 Apr 2022 14:07:58 +0200 Subject: [PATCH 069/275] Added equals/hashCode contract to Vector2D/Vector3D --- .../kmath/geometry/Euclidean2DSpace.kt | 24 ++++++++- .../kmath/geometry/Euclidean3DSpace.kt | 24 ++++++++- .../kscience/kmath/geometry/Vector2DTest.kt | 50 +++++++++++++++++ .../kscience/kmath/geometry/Vector3DTest.kt | 53 +++++++++++++++++++ 4 files changed, 149 insertions(+), 2 deletions(-) diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt index d00575bcc..6b1f9c2eb 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 @@ -24,6 +24,19 @@ public interface Vector2D : Point, Vector { } override operator fun iterator(): Iterator = listOf(x, y).iterator() + + /** + * Indicates whether some other vector is "equal to" this one. + * Any [Vector3D] is considered equal, if it contains the same components. + */ + override fun equals(other: Any?): Boolean + + /** + * Returns a hash code value for this vector. + * The hash code is generated as if all the input values were placed into + * a list, and that list were hashed by calling `listOf(x, y).hashCode()`. + */ + override fun hashCode(): Int } public val Vector2D.r: Double @@ -35,7 +48,16 @@ public fun Vector2D(x: Double, y: Double): Vector2D = Vector2DImpl(x, y) private data class Vector2DImpl( override val x: Double, override val y: Double, -) : Vector2D +) : Vector2D { + + override fun equals(other: Any?) = when (other) { + this -> true + is Vector2D -> x == other.x && y == other.y + else -> false + } + + override fun hashCode(): Int = listOf(x, y).hashCode() +} /** * 2D Euclidean space diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt index e12563b46..bc991d597 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 @@ -26,6 +26,19 @@ public interface Vector3D : Point, Vector { } override operator fun iterator(): Iterator = listOf(x, y, z).iterator() + + /** + * Indicates whether some other vector is "equal to" this one. + * Any [Vector3D] is considered equal, if it contains the same components. + */ + override fun equals(other: Any?): Boolean + + /** + * Returns a hash code value for this vector. + * The hash code is generated as if all the input values were placed into + * a list, and that list were hashed by calling `listOf(x, y, z).hashCode()`. + */ + override fun hashCode(): Int } @Suppress("FunctionName") @@ -37,7 +50,16 @@ private data class Vector3DImpl( override val x: Double, override val y: Double, override val z: Double, -) : Vector3D +) : Vector3D { + + override fun equals(other: Any?) = when (other) { + this -> true + is Vector3D -> x == other.x && y == other.y && z == other.z + else -> false + } + + override fun hashCode() = listOf(x, y, z).hashCode() +} public object Euclidean3DSpace : GeometrySpace, ScaleOperations { override val zero: Vector3D by lazy { Vector3D(0.0, 0.0, 0.0) } diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Vector2DTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Vector2DTest.kt index 5e45b4870..94ec7ef90 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 @@ -37,4 +37,54 @@ internal class Vector2DTest { fun y() { assertEquals(-7.999, vector.y) } + + @Test + fun equality() { + val vector2 = AlternativeVector2D(1.0, -7.999) + + // reflexive + assertEquals(vector, vector) + assertEquals(vector2, vector2) + + // symmetric + assertEquals(vector, vector2) + assertEquals(vector2, vector) + + // transitive + val vector3 = AlternativeVector2D(1.0, -7.999) + assertEquals(vector, vector2) + assertEquals(vector2, vector3) + assertEquals(vector3, vector) + } + + @Test + fun hash() { + val vector2 = AlternativeVector2D(1.0, -7.999) + + assertEquals(vector, vector2) + assertEquals(vector.hashCode(), vector2.hashCode()) + } + + private data class AlternativeVector2D( + override val x: Double, + override val y: Double, + ) : Vector2D { + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other == null || other !is Vector2D) return false + + if (x != other.x) return false + if (y != other.y) return false + + return true + } + + override fun hashCode(): Int { + var result = 1 + result = 31 * result + x.hashCode() + result = 31 * result + y.hashCode() + return result + } + } } diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Vector3DTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Vector3DTest.kt index 55bab4775..92fbf37aa 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 @@ -43,4 +43,57 @@ internal class Vector3DTest { fun z() { assertEquals(0.001, vector.z) } + + @Test + fun equality() { + val vector2 = AlternativeVector3D(1.0, -7.999, 0.001) + + // reflexive + assertEquals(vector, vector) + assertEquals(vector2, vector2) + + // symmetric + assertEquals(vector, vector2) + assertEquals(vector2, vector) + + // transitive + val vector3 = AlternativeVector3D(1.0, -7.999, 0.001) + assertEquals(vector, vector2) + assertEquals(vector2, vector3) + assertEquals(vector3, vector) + } + + @Test + fun hash() { + val vector2 = AlternativeVector3D(1.0, -7.999, 0.001) + + assertEquals(vector, vector2) + assertEquals(vector.hashCode(), vector2.hashCode()) + } + + private data class AlternativeVector3D( + override val x: Double, + override val y: Double, + override val z: Double, + ) : Vector3D { + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other == null || other !is Vector3D) return false + + if (x != other.x) return false + if (y != other.y) return false + if (z != other.z) return false + + return true + } + + override fun hashCode(): Int { + var result = 1 + result = 31 * result + x.hashCode() + result = 31 * result + y.hashCode() + result = 31 * result + z.hashCode() + return result + } + } } -- 2.34.1 From c28be8322697c72237544522d8a8c143f688979d Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 8 Jun 2022 09:00:37 +0300 Subject: [PATCH 070/275] LazyStructire::deferred -> async --- CHANGELOG.md | 2 ++ build.gradle.kts | 2 +- buildSrc/build.gradle.kts | 1 + buildSrc/gradle.properties | 2 +- .../kscience/kmath/nd/VirtualStructureND.kt | 16 ++++++++++++++++ .../kscience/kmath/structures/LazyStructureND.kt | 10 +++++----- 6 files changed, 26 insertions(+), 7 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/VirtualStructureND.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 75833602c..c4b8c06cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### Added ### Changed +- Kotlin 1.7 +- `LazyStructure` `deffered` -> `async` to comply with coroutines code style ### Deprecated diff --git a/build.gradle.kts b/build.gradle.kts index 10f2385f5..9fa012fb2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,7 +11,7 @@ allprojects { } group = "space.kscience" - version = "0.3.0" + version = "0.3.1" } subprojects { diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index fa5142538..dcb39d448 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -1,4 +1,5 @@ plugins { + kotlin("jvm") version "1.7.0-RC" `kotlin-dsl` `version-catalog` alias(miptNpmLibs.plugins.kotlin.plugin.serialization) diff --git a/buildSrc/gradle.properties b/buildSrc/gradle.properties index a0b05e812..751caec36 100644 --- a/buildSrc/gradle.properties +++ b/buildSrc/gradle.properties @@ -4,4 +4,4 @@ # kotlin.code.style=official -toolsVersion=0.11.2-kotlin-1.6.10 +toolsVersion=0.11.5-kotlin-1.7.0-RC diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/VirtualStructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/VirtualStructureND.kt new file mode 100644 index 000000000..799d14b3d --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/VirtualStructureND.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.nd + +public open class VirtualStructureND( + override val shape: Shape, + public val producer: (IntArray) -> T, +) : StructureND { + override fun get(index: IntArray): T { + require(check that index is in the shape boundaries) + return producer(index) + } +} \ No newline at end of file diff --git a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt index ac9eb773a..2b9265843 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 @@ -18,12 +18,12 @@ public class LazyStructureND( ) : StructureND { private val cache: MutableMap> = HashMap() - public fun deferred(index: IntArray): Deferred = cache.getOrPut(index) { + public fun async(index: IntArray): Deferred = cache.getOrPut(index) { scope.async(context = Dispatchers.Math) { function(index) } } - public suspend fun await(index: IntArray): T = deferred(index).await() - override operator fun get(index: IntArray): T = runBlocking { deferred(index).await() } + public suspend fun await(index: IntArray): T = async(index).await() + override operator fun get(index: IntArray): T = runBlocking { async(index).await() } @OptIn(PerformancePitfall::class) override fun elements(): Sequence> { @@ -33,8 +33,8 @@ public class LazyStructureND( } } -public fun StructureND.deferred(index: IntArray): Deferred = - if (this is LazyStructureND) deferred(index) else CompletableDeferred(get(index)) +public fun StructureND.async(index: IntArray): Deferred = + if (this is LazyStructureND) this@async.async(index) else CompletableDeferred(get(index)) public suspend fun StructureND.await(index: IntArray): T = if (this is LazyStructureND) await(index) else get(index) -- 2.34.1 From de9f3cc8df4ebb0c05ee81d6a77922174e8d532c Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Fri, 10 Jun 2022 23:37:50 +0300 Subject: [PATCH 071/275] Inlined LaTeX formula. Now GitHub supports MathJax! --- kmath-ast/README.md | 5 +---- kmath-ast/docs/README-TEMPLATE.md | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/kmath-ast/README.md b/kmath-ast/README.md index 5d5630f46..cc5f5b764 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -199,10 +199,7 @@ public fun main() { Result LaTeX: -

- -![](https://latex.codecogs.com/gif.latex?%5Coperatorname{exp}%5C,%5Cleft(%5Csqrt{x}%5Cright)-%5Cfrac{%5Cfrac{%5Coperatorname{arcsin}%5C,%5Cleft(2%5C,x%5Cright)}{2%5Ctimes10^{10}%2Bx^{3}}}{12}+x^{2/3}) -
+$$\operatorname{exp}\\,\left(\sqrt{x}\right)-\frac{\frac{\operatorname{arcsin}\\,\left(2\,x\right)}{2\times10^{10}%2Bx^{3}}}{12}+x^{2/3}$$ Result MathML (can be used with MathJax or other renderers): diff --git a/kmath-ast/docs/README-TEMPLATE.md b/kmath-ast/docs/README-TEMPLATE.md index e9e22f4d4..1f14deaba 100644 --- a/kmath-ast/docs/README-TEMPLATE.md +++ b/kmath-ast/docs/README-TEMPLATE.md @@ -170,10 +170,7 @@ public fun main() { Result LaTeX: -
- -![](https://latex.codecogs.com/gif.latex?%5Coperatorname{exp}%5C,%5Cleft(%5Csqrt{x}%5Cright)-%5Cfrac{%5Cfrac{%5Coperatorname{arcsin}%5C,%5Cleft(2%5C,x%5Cright)}{2%5Ctimes10^{10}%2Bx^{3}}}{12}+x^{2/3}) -
+$$\operatorname{exp}\\,\left(\sqrt{x}\right)-\frac{\frac{\operatorname{arcsin}\\,\left(2\,x\right)}{2\times10^{10}%2Bx^{3}}}{12}+x^{2/3}$$ Result MathML (can be used with MathJax or other renderers): -- 2.34.1 From b92ef23f5d3ec2c2578abc6f8734a12cd837bbf9 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sat, 11 Jun 2022 00:06:45 +0300 Subject: [PATCH 072/275] Some fixes --- kmath-ast/README.md | 2 +- kmath-ast/docs/README-TEMPLATE.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kmath-ast/README.md b/kmath-ast/README.md index cc5f5b764..553c60bb3 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -199,7 +199,7 @@ public fun main() { Result LaTeX: -$$\operatorname{exp}\\,\left(\sqrt{x}\right)-\frac{\frac{\operatorname{arcsin}\\,\left(2\,x\right)}{2\times10^{10}%2Bx^{3}}}{12}+x^{2/3}$$ +$$\operatorname{exp}\\,\left(\sqrt{x}\right)-\frac{\frac{\operatorname{arcsin}\\,\left(2\\,x\right)}{2\times10^{10}+x^{3}}}{12}+x^{2/3}$$ Result MathML (can be used with MathJax or other renderers): diff --git a/kmath-ast/docs/README-TEMPLATE.md b/kmath-ast/docs/README-TEMPLATE.md index 1f14deaba..96bbfbf5a 100644 --- a/kmath-ast/docs/README-TEMPLATE.md +++ b/kmath-ast/docs/README-TEMPLATE.md @@ -170,7 +170,7 @@ public fun main() { Result LaTeX: -$$\operatorname{exp}\\,\left(\sqrt{x}\right)-\frac{\frac{\operatorname{arcsin}\\,\left(2\,x\right)}{2\times10^{10}%2Bx^{3}}}{12}+x^{2/3}$$ +$$\operatorname{exp}\\,\left(\sqrt{x}\right)-\frac{\frac{\operatorname{arcsin}\\,\left(2\\,x\right)}{2\times10^{10}+x^{3}}}{12}+x^{2/3}$$ Result MathML (can be used with MathJax or other renderers): -- 2.34.1 From 89cdbf4d71f188105f12bb9029dc3c0f40a87360 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sat, 11 Jun 2022 15:58:25 +0300 Subject: [PATCH 073/275] Changed names of algebraic stub. Added FIXMEs about KT-31420. Changed JVM/JS names style. --- .../kscience/kmath/functions/Polynomial.kt | 112 +++++----- .../kmath/functions/RationalFunction.kt | 208 +++++++++--------- .../kscience/kmath/functions/algebraicStub.kt | 48 ++-- .../kmath/functions/labeledPolynomialUtil.kt | 16 +- .../kmath/functions/numberedPolynomialUtil.kt | 16 +- .../kmath/functions/AlgebraicStubTest.kt | 208 +++++++++--------- 6 files changed, 304 insertions(+), 304 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 96e860550..e201f1f6e 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -22,7 +22,7 @@ public interface Polynomial * @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") +@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 constant (member of underlying ring). @@ -76,38 +76,38 @@ public interface PolynomialSpace> : Ring

{ * * The operation is equivalent to adding [other] copies of unit polynomial to [this]. */ - public operator fun P.plus(other: Int): P = addMultipliedBySquaring(this, one, other) + public operator fun P.plus(other: Int): P = addMultipliedByDoubling(this, one, other) /** * Returns difference between the polynomial and the integer represented as polynomial. * * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. */ - public operator fun P.minus(other: Int): P = addMultipliedBySquaring(this, one, -other) + public operator fun P.minus(other: Int): P = addMultipliedByDoubling(this, one, -other) /** * Returns product of the polynomial and the integer represented as polynomial. * * The operation is equivalent to sum of [other] copies of [this]. */ - public operator fun P.times(other: Int): P = multiplyBySquaring(this, other) + public operator fun P.times(other: Int): P = multiplyByDoubling(this, other) /** * Returns sum of the integer represented as 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 = addMultipliedBySquaring(other, one, this) + public operator fun Int.plus(other: P): P = addMultipliedByDoubling(other, one, this) /** * Returns difference between the integer represented as 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 = addMultipliedBySquaring(-other, one, this) + public operator fun Int.minus(other: P): P = addMultipliedByDoubling(-other, one, this) /** * Returns product of the integer represented as polynomial and the polynomial. * * The operation is equivalent to sum of [this] copies of [other]. */ - public operator fun Int.times(other: P): P = multiplyBySquaring(other, this) + public operator fun Int.times(other: P): P = multiplyByDoubling(other, this) /** * Converts the integer [value] to polynomial. @@ -121,38 +121,38 @@ public interface PolynomialSpace> : Ring

{ /** * Returns the same constant. */ - @JvmName("constantUnaryPlus") - @JsName("constantUnaryPlus") + @JvmName("unaryPlusConstant") + @JsName("unaryPlusConstant") public operator fun C.unaryPlus(): C = this /** * Returns negation of the constant. */ - @JvmName("constantUnaryMinus") - @JsName("constantUnaryMinus") + @JvmName("unaryMinusConstant") + @JsName("unaryMinusConstant") public operator fun C.unaryMinus(): C /** * Returns sum of the constants. */ - @JvmName("constantPlus") - @JsName("constantPlus") + @JvmName("plusConstantConstant") + @JsName("plusConstantConstant") public operator fun C.plus(other: C): C /** * Returns difference of the constants. */ - @JvmName("constantMinus") - @JsName("constantMinus") + @JvmName("minusConstantConstant") + @JsName("minusConstantConstant") public operator fun C.minus(other: C): C /** * Returns product of the constants. */ - @JvmName("constantTimes") - @JsName("constantTimes") + @JvmName("timesConstantConstant") + @JsName("timesConstantConstant") public operator fun C.times(other: C): C /** * Raises [arg] to the integer power [exponent]. */ - @JvmName("constantPower") - @JsName("constantPower") + @JvmName("powerConstant") + @JsName("powerConstant") public fun power(arg: C, exponent: UInt) : C /** @@ -222,7 +222,7 @@ public interface PolynomialSpace> : Ring

{ /** * Raises [arg] to the integer power [exponent]. */ - public override fun power(arg: P, exponent: UInt) : P = exponentiationBySquaring(arg, exponent) + public override fun power(arg: P, exponent: UInt) : P = exponentiateBySquaring(arg, exponent) /** * Instance of zero polynomial (zero of the polynomial ring). @@ -251,7 +251,7 @@ public interface PolynomialSpace> : Ring

{ * @param P the type of polynomials. * @param A the type of algebraic structure (precisely, of ring) provided for constants. */ -@Suppress("INAPPLICABLE_JVM_NAME") +@Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 public interface PolynomialSpaceOverRing, A: Ring> : PolynomialSpace { public val ring: A @@ -261,63 +261,63 @@ public interface PolynomialSpaceOverRing, A: Ring> : Poly * * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. */ - public override operator fun C.plus(other: Int): C = ring { addMultipliedBySquaring(this@plus, one, other) } + 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 constant (member of underlying ring). * * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. */ - public override operator fun C.minus(other: Int): C = ring { addMultipliedBySquaring(this@minus, one, -other) } + 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 constant (member of underlying ring). * * The operation is equivalent to sum of [other] copies of [this]. */ - public override operator fun C.times(other: Int): C = ring { multiplyBySquaring(this@times, other) } + public override operator fun C.times(other: Int): C = ring { multiplyByDoubling(this@times, other) } /** * Returns sum of the integer represented as constant (member of underlying ring) and the constant. * * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. */ - public override operator fun Int.plus(other: C): C = ring { addMultipliedBySquaring(other, one, this@plus) } + public override operator fun Int.plus(other: C): C = ring { addMultipliedByDoubling(other, one, this@plus) } /** * Returns difference between the integer represented as constant (member of underlying ring) and the constant. * * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. */ - public override operator fun Int.minus(other: C): C = ring { addMultipliedBySquaring(-other, one, this@minus) } + public override operator fun Int.minus(other: C): C = ring { addMultipliedByDoubling(-other, one, this@minus) } /** * Returns product of the integer represented as constant (member of underlying ring) and the constant. * * The operation is equivalent to sum of [this] copies of [other]. */ - public override operator fun Int.times(other: C): C = ring { multiplyBySquaring(other, this@times) } + public override operator fun Int.times(other: C): C = ring { multiplyByDoubling(other, this@times) } /** * Returns negation of the constant. */ - @JvmName("constantUnaryMinus") + @JvmName("unaryMinusConstant") public override operator fun C.unaryMinus(): C = ring { -this@unaryMinus } /** * Returns sum of the constants. */ - @JvmName("constantPlus") + @JvmName("plusConstantConstant") public override operator fun C.plus(other: C): C = ring { this@plus + other } /** * Returns difference of the constants. */ - @JvmName("constantMinus") + @JvmName("minusConstantConstant") public override operator fun C.minus(other: C): C = ring { this@minus - other } /** * Returns product of the constants. */ - @JvmName("constantTimes") + @JvmName("timesConstantConstant") public override operator fun C.times(other: C): C = ring { this@times * other } /** * Raises [arg] to the integer power [exponent]. */ - @JvmName("constantPower") + @JvmName("powerConstant") override fun power(arg: C, exponent: UInt): C = ring { power(arg, exponent) } /** @@ -330,59 +330,59 @@ public interface PolynomialSpaceOverRing, A: Ring> : Poly public override val constantOne: C get() = ring.one } -@Suppress("INAPPLICABLE_JVM_NAME") +@Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 public interface MultivariatePolynomialSpace>: PolynomialSpace { - @JvmName("VariableIntPlus") + @JvmName("plusVariableInt") public operator fun V.plus(other: Int): P - @JvmName("VariableIntMinus") + @JvmName("minusVariableInt") public operator fun V.minus(other: Int): P - @JvmName("VariableIntMinusTimes") + @JvmName("timesVariableInt") public operator fun V.times(other: Int): P - @JvmName("IntVariablePlus") + @JvmName("plusIntVariable") public operator fun Int.plus(other: V): P - @JvmName("IntVariableMinus") + @JvmName("minusIntVariable") public operator fun Int.minus(other: V): P - @JvmName("IntVariableTimes") + @JvmName("timesIntVariable") public operator fun Int.times(other: V): P - @JvmName("ConstantVariablePlus") + @JvmName("plusConstantVariable") public operator fun C.plus(other: V): P - @JvmName("ConstantVariableMinus") + @JvmName("minusConstantVariable") public operator fun C.minus(other: V): P - @JvmName("ConstantVariableTimes") + @JvmName("timesConstantVariable") public operator fun C.times(other: V): P - @JvmName("VariableConstantPlus") + @JvmName("plusVariableConstant") public operator fun V.plus(other: C): P - @JvmName("VariableConstantMinus") + @JvmName("minusVariableConstant") public operator fun V.minus(other: C): P - @JvmName("VariableConstantTimes") + @JvmName("timesVariableConstant") public operator fun V.times(other: C): P - @JvmName("VariableUnaryPlus") + @JvmName("unaryPlusVariable") public operator fun V.unaryPlus(): P - @JvmName("VariableUnaryMinus") + @JvmName("unaryMinusVariable") public operator fun V.unaryMinus(): P - @JvmName("VariablePlus") + @JvmName("plusVariableVariable") public operator fun V.plus(other: V): P - @JvmName("VariableMinus") + @JvmName("minusVariableVariable") public operator fun V.minus(other: V): P - @JvmName("VariableTimes") + @JvmName("timesVariableVariable") public operator fun V.times(other: V): P - @JvmName("VariablePolynomialPlus") + @JvmName("plusVariablePolynomial") public operator fun V.plus(other: P): P - @JvmName("VariablePolynomialMinus") + @JvmName("minusVariablePolynomial") public operator fun V.minus(other: P): P - @JvmName("VariablePolynomialTimes") + @JvmName("timesVariablePolynomial") public operator fun V.times(other: P): P - @JvmName("PolynomialVariablePlus") + @JvmName("plusPolynomialVariable") public operator fun P.plus(other: V): P - @JvmName("PolynomialVariableMinus") + @JvmName("minusPolynomialVariable") public operator fun P.minus(other: V): P - @JvmName("PolynomialVariableTimes") + @JvmName("timesPolynomialVariable") public operator fun P.times(other: V): P /** diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index eede543ee..dfec126f3 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -28,7 +28,7 @@ public interface RationalFunction> { * @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", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") +@Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") // FIXME: Waiting for KT-31420 public interface RationalFunctionalSpace, R: RationalFunction> : Ring { /** * Returns sum of the constant and the integer represented as constant (member of underlying ring). @@ -129,52 +129,52 @@ public interface RationalFunctionalSpace, R: RationalFunctio * * The operation is equivalent to adding [other] copies of unit polynomial to [this]. */ - public operator fun R.plus(other: Int): R = addMultipliedBySquaring(this, one, other) + public operator fun R.plus(other: Int): R = addMultipliedByDoubling(this, one, other) /** * Returns difference between the rational function and the integer represented as rational function. * * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. */ - public operator fun R.minus(other: Int): R = addMultipliedBySquaring(this, one, -other) + public operator fun R.minus(other: Int): R = addMultipliedByDoubling(this, one, -other) /** * Returns product of the rational function and the integer represented as rational function. * * The operation is equivalent to sum of [other] copies of [this]. */ - public operator fun R.times(other: Int): R = multiplyBySquaring(this, other) + public operator fun R.times(other: Int): R = multiplyByDoubling(this, other) /** * Returns quotient of the rational function and the integer represented as 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 / multiplyBySquaring(one, other) + public operator fun R.div(other: Int): R = this / multiplyByDoubling(one, other) /** * Returns sum of the integer represented as 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 = addMultipliedBySquaring(other, one, this) + public operator fun Int.plus(other: R): R = addMultipliedByDoubling(other, one, this) /** * Returns difference between the integer represented as 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 = addMultipliedBySquaring(-other, one, this) + public operator fun Int.minus(other: R): R = addMultipliedByDoubling(-other, one, this) /** * Returns product of the integer represented as 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 = multiplyBySquaring(other, this) + public operator fun Int.times(other: R): R = multiplyByDoubling(other, this) /** * Returns quotient of the integer represented as 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 = multiplyBySquaring(one / other, this) + public operator fun Int.div(other: R): R = multiplyByDoubling(one / other, this) /** * Converts the integer [value] to rational function. @@ -188,38 +188,38 @@ public interface RationalFunctionalSpace, R: RationalFunctio /** * Returns the same constant. */ - @JvmName("constantUnaryPlus") - @JsName("constantUnaryPlus") + @JvmName("unaryPlusConstant") + @JsName("unaryPlusConstant") public operator fun C.unaryPlus(): C = this /** * Returns negation of the constant. */ - @JvmName("constantUnaryMinus") - @JsName("constantUnaryMinus") + @JvmName("unaryMinusConstant") + @JsName("unaryMinusConstant") public operator fun C.unaryMinus(): C /** * Returns sum of the constants. */ - @JvmName("constantPlus") - @JsName("constantPlus") + @JvmName("plusConstantConstant") + @JsName("plusConstantConstant") public operator fun C.plus(other: C): C /** * Returns difference of the constants. */ - @JvmName("constantMinus") - @JsName("constantMinus") + @JvmName("minusConstantConstant") + @JsName("minusConstantConstant") public operator fun C.minus(other: C): C /** * Returns product of the constants. */ - @JvmName("constantTimes") - @JsName("constantTimes") + @JvmName("timesConstantConstant") + @JsName("timesConstantConstant") public operator fun C.times(other: C): C /** * Raises [arg] to the integer power [exponent]. */ - @JvmName("constantPower") - @JsName("constantPower") + @JvmName("powerConstant") + @JsName("powerConstant") public fun power(arg: C, exponent: UInt) : C /** @@ -417,7 +417,7 @@ public interface RationalFunctionalSpace, R: RationalFunctio /** * Raises [arg] to the integer power [exponent]. */ - public override fun power(arg: R, exponent: UInt) : R = exponentiationBySquaring(arg, exponent) + public override fun power(arg: R, exponent: UInt) : R = exponentiateBySquaring(arg, exponent) /** * Instance of zero rational function (zero of the rational functions ring). @@ -458,7 +458,7 @@ public interface RationalFunctionalSpace, R: RationalFunctio * @param R the type of rational functions. * @param A the type of algebraic structure (precisely, of ring) provided for constants. */ -@Suppress("INAPPLICABLE_JVM_NAME") +@Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 public interface RationalFunctionalSpaceOverRing, R: RationalFunction, A: Ring> : RationalFunctionalSpace { public val ring: A @@ -468,68 +468,68 @@ public interface RationalFunctionalSpaceOverRing, R: Rationa * * The operation is equivalent to adding [other] copies of unit of underlying ring to [this]. */ - public override operator fun C.plus(other: Int): C = ring { addMultipliedBySquaring(this@plus, one, other) } + 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 constant (member of underlying ring). * * The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this]. */ - public override operator fun C.minus(other: Int): C = ring { addMultipliedBySquaring(this@minus, one, -other) } + 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 constant (member of underlying ring). * * The operation is equivalent to sum of [other] copies of [this]. */ - public override operator fun C.times(other: Int): C = ring { multiplyBySquaring(this@times, other) } + public override operator fun C.times(other: Int): C = ring { multiplyByDoubling(this@times, other) } /** * Returns sum of the integer represented as constant (member of underlying ring) and the constant. * * The operation is equivalent to adding [this] copies of unit of underlying ring to [other]. */ - public override operator fun Int.plus(other: C): C = ring { addMultipliedBySquaring(other, one, this@plus) } + public override operator fun Int.plus(other: C): C = ring { addMultipliedByDoubling(other, one, this@plus) } /** * Returns difference between the integer represented as constant (member of underlying ring) and the constant. * * The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other]. */ - public override operator fun Int.minus(other: C): C = ring { addMultipliedBySquaring(-other, one, this@minus) } + public override operator fun Int.minus(other: C): C = ring { addMultipliedByDoubling(-other, one, this@minus) } /** * Returns product of the integer represented as constant (member of underlying ring) and the constant. * * The operation is equivalent to sum of [this] copies of [other]. */ - public override operator fun Int.times(other: C): C = ring { multiplyBySquaring(other, this@times) } + public override operator fun Int.times(other: C): C = ring { multiplyByDoubling(other, this@times) } /** * Returns the same constant. */ - @JvmName("constantUnaryPlus") + @JvmName("unaryPlusConstant") public override operator fun C.unaryPlus(): C = ring { +this@unaryPlus } /** * Returns negation of the constant. */ - @JvmName("constantUnaryMinus") + @JvmName("unaryMinusConstant") public override operator fun C.unaryMinus(): C = ring { -this@unaryMinus } /** * Returns sum of the constants. */ - @JvmName("constantPlus") + @JvmName("plusConstantConstant") public override operator fun C.plus(other: C): C = ring { this@plus + other } /** * Returns difference of the constants. */ - @JvmName("constantMinus") + @JvmName("minusConstantConstant") public override operator fun C.minus(other: C): C = ring { this@minus - other } /** * Returns product of the constants. */ - @JvmName("constantTimes") + @JvmName("timesConstantConstant") public override operator fun C.times(other: C): C = ring { this@times * other } /** * Raises [arg] to the integer power [exponent]. */ - @JvmName("constantPower") + @JvmName("powerConstant") public override fun power(arg: C, exponent: UInt) : C = ring { power(arg, exponent) } /** @@ -552,7 +552,7 @@ public interface RationalFunctionalSpaceOverRing, R: Rationa * @param R the type of rational functions. * @param AP the type of algebraic structure (precisely, of ring) provided for polynomials. */ -@Suppress("INAPPLICABLE_JVM_NAME") +@Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 public interface RationalFunctionalSpaceOverPolynomialSpace< C, P: Polynomial, @@ -659,32 +659,32 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< /** * Returns the same constant. */ - @JvmName("constantUnaryPlus") + @JvmName("unaryPlusConstant") public override operator fun C.unaryPlus(): C = polynomialRing { +this@unaryPlus } /** * Returns negation of the constant. */ - @JvmName("constantUnaryMinus") + @JvmName("unaryMinusConstant") public override operator fun C.unaryMinus(): C = polynomialRing { -this@unaryMinus } /** * Returns sum of the constants. */ - @JvmName("constantPlus") + @JvmName("plusConstantConstant") public override operator fun C.plus(other: C): C = polynomialRing { this@plus + other } /** * Returns difference of the constants. */ - @JvmName("constantMinus") + @JvmName("minusConstantConstant") public override operator fun C.minus(other: C): C = polynomialRing { this@minus - other } /** * Returns product of the constants. */ - @JvmName("constantTimes") + @JvmName("timesConstantConstant") public override operator fun C.times(other: C): C = polynomialRing { this@times * other } /** * Raises [arg] to the integer power [exponent]. */ - @JvmName("constantPower") + @JvmName("powerConstant") public override fun power(arg: C, exponent: UInt) : C = polynomialRing { power(arg, exponent) } /** @@ -780,7 +780,7 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< * @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") +@Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 public abstract class PolynomialSpaceOfFractions< C, P: Polynomial, @@ -1052,78 +1052,78 @@ public abstract class PolynomialSpaceOfFractions< public override val one: R get() = constructRationalFunction(polynomialOne) } -@Suppress("INAPPLICABLE_JVM_NAME") +@Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 public interface MultivariateRationalFunctionalSpace< C, V, P: Polynomial, R: RationalFunction >: RationalFunctionalSpace { - @JvmName("VariableIntPlus") + @JvmName("plusVariableInt") public operator fun V.plus(other: Int): P - @JvmName("VariableIntMinus") + @JvmName("minusVariableInt") public operator fun V.minus(other: Int): P - @JvmName("VariableIntMinusTimes") + @JvmName("timesVariableInt") public operator fun V.times(other: Int): P - @JvmName("IntVariablePlus") + @JvmName("plusIntVariable") public operator fun Int.plus(other: V): P - @JvmName("IntVariableMinus") + @JvmName("minusIntVariable") public operator fun Int.minus(other: V): P - @JvmName("IntVariableTimes") + @JvmName("timesIntVariable") public operator fun Int.times(other: V): P - @JvmName("ConstantVariablePlus") + @JvmName("plusConstantVariable") public operator fun C.plus(other: V): P - @JvmName("ConstantVariableMinus") + @JvmName("minusConstantVariable") public operator fun C.minus(other: V): P - @JvmName("ConstantVariableTimes") + @JvmName("timesConstantVariable") public operator fun C.times(other: V): P - @JvmName("VariableConstantPlus") + @JvmName("plusVariableConstant") public operator fun V.plus(other: C): P - @JvmName("VariableConstantMinus") + @JvmName("minusVariableConstant") public operator fun V.minus(other: C): P - @JvmName("VariableConstantTimes") + @JvmName("timesVariableConstant") public operator fun V.times(other: C): P - @JvmName("VariableUnaryPlus") + @JvmName("unaryPlusVariable") public operator fun V.unaryPlus(): P - @JvmName("VariableUnaryMinus") + @JvmName("unaryMinusVariable") public operator fun V.unaryMinus(): P - @JvmName("VariablePlus") + @JvmName("plusVariableVariable") public operator fun V.plus(other: V): P - @JvmName("VariableMinus") + @JvmName("minusVariableVariable") public operator fun V.minus(other: V): P - @JvmName("VariableTimes") + @JvmName("timesVariableVariable") public operator fun V.times(other: V): P - @JvmName("VariablePolynomialPlus") + @JvmName("plusVariablePolynomial") public operator fun V.plus(other: P): P - @JvmName("VariablePolynomialMinus") + @JvmName("minusVariablePolynomial") public operator fun V.minus(other: P): P - @JvmName("VariablePolynomialTimes") + @JvmName("timesVariablePolynomial") public operator fun V.times(other: P): P - @JvmName("PolynomialVariablePlus") + @JvmName("plusPolynomialVariable") public operator fun P.plus(other: V): P - @JvmName("PolynomialVariableMinus") + @JvmName("minusPolynomialVariable") public operator fun P.minus(other: V): P - @JvmName("PolynomialVariableTimes") + @JvmName("timesPolynomialVariable") public operator fun P.times(other: V): P - @JvmName("VariableRationalFunctionPlus") + @JvmName("plusVariableRational") public operator fun V.plus(other: R): R - @JvmName("VariableRationalFunctionMinus") + @JvmName("minusVariableRational") public operator fun V.minus(other: R): R - @JvmName("VariableRationalFunctionTimes") + @JvmName("timesVariableRational") public operator fun V.times(other: R): R - @JvmName("RationalFunctionVariablePlus") + @JvmName("plusRationalVariable") public operator fun R.plus(other: V): R - @JvmName("RationalFunctionVariableMinus") + @JvmName("minusRationalVariable") public operator fun R.minus(other: V): R - @JvmName("RationalFunctionVariableTimes") + @JvmName("timesRationalVariable") public operator fun R.times(other: V): R /** @@ -1177,7 +1177,7 @@ public interface MultivariateRationalFunctionalSpaceOverPolynomialSpace< AP: PolynomialSpace, > : RationalFunctionalSpaceOverPolynomialSpace, MultivariateRationalFunctionalSpace -@Suppress("INAPPLICABLE_JVM_NAME") +@Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 public interface MultivariateRationalFunctionalSpaceOverMultivariatePolynomialSpace< C, V, @@ -1185,57 +1185,57 @@ public interface MultivariateRationalFunctionalSpaceOverMultivariatePolynomialSp R: RationalFunction, AP: MultivariatePolynomialSpace, > : MultivariateRationalFunctionalSpaceOverPolynomialSpace { - @JvmName("VariableIntPlus") + @JvmName("plusVariableInt") public override operator fun V.plus(other: Int): P = polynomialRing { this@plus + other } - @JvmName("VariableIntMinus") + @JvmName("minusVariableInt") public override operator fun V.minus(other: Int): P = polynomialRing { this@minus - other } - @JvmName("VariableIntMinusTimes") + @JvmName("timesVariableInt") public override operator fun V.times(other: Int): P = polynomialRing { this@times * other } - @JvmName("IntVariablePlus") + @JvmName("plusIntVariable") public override operator fun Int.plus(other: V): P = polynomialRing { this@plus + other } - @JvmName("IntVariableMinus") + @JvmName("minusIntVariable") public override operator fun Int.minus(other: V): P = polynomialRing { this@minus - other } - @JvmName("IntVariableTimes") + @JvmName("timesIntVariable") public override operator fun Int.times(other: V): P = polynomialRing { this@times * other } - @JvmName("ConstantVariablePlus") + @JvmName("plusConstantVariable") public override operator fun C.plus(other: V): P = polynomialRing { this@plus + other } - @JvmName("ConstantVariableMinus") + @JvmName("minusConstantVariable") public override operator fun C.minus(other: V): P = polynomialRing { this@minus - other } - @JvmName("ConstantVariableTimes") + @JvmName("timesConstantVariable") public override operator fun C.times(other: V): P = polynomialRing { this@times * other } - @JvmName("VariableConstantPlus") + @JvmName("plusVariableConstant") public override operator fun V.plus(other: C): P = polynomialRing { this@plus + other } - @JvmName("VariableConstantMinus") + @JvmName("minusVariableConstant") public override operator fun V.minus(other: C): P = polynomialRing { this@minus - other } - @JvmName("VariableConstantTimes") + @JvmName("timesVariableConstant") public override operator fun V.times(other: C): P = polynomialRing { this@times * other } - @JvmName("VariableUnaryPlus") + @JvmName("unaryPlusVariable") public override operator fun V.unaryPlus(): P = polynomialRing { +this@unaryPlus } - @JvmName("VariableUnaryMinus") + @JvmName("unaryMinusVariable") public override operator fun V.unaryMinus(): P = polynomialRing { -this@unaryMinus } - @JvmName("VariablePlus") + @JvmName("plusVariableVariable") public override operator fun V.plus(other: V): P = polynomialRing { this@plus + other } - @JvmName("VariableMinus") + @JvmName("minusVariableVariable") public override operator fun V.minus(other: V): P = polynomialRing { this@minus - other } - @JvmName("VariableTimes") + @JvmName("timesVariableVariable") public override operator fun V.times(other: V): P = polynomialRing { this@times * other } - @JvmName("VariablePolynomialPlus") + @JvmName("plusVariablePolynomial") public override operator fun V.plus(other: P): P = polynomialRing { this@plus + other } - @JvmName("VariablePolynomialMinus") + @JvmName("minusVariablePolynomial") public override operator fun V.minus(other: P): P = polynomialRing { this@minus - other } - @JvmName("VariablePolynomialTimes") + @JvmName("timesVariablePolynomial") public override operator fun V.times(other: P): P = polynomialRing { this@times * other } - @JvmName("PolynomialVariablePlus") + @JvmName("plusPolynomialVariable") public override operator fun P.plus(other: V): P = polynomialRing { this@plus + other } - @JvmName("PolynomialVariableMinus") + @JvmName("minusPolynomialVariable") public override operator fun P.minus(other: V): P = polynomialRing { this@minus - other } - @JvmName("PolynomialVariableTimes") + @JvmName("timesPolynomialVariable") public override operator fun P.times(other: V): P = polynomialRing { this@times * other } /** @@ -1264,45 +1264,45 @@ public interface MultivariateRationalFunctionalSpaceOverMultivariatePolynomialSp public override val P.countOfVariables: Int get() = polynomialRing { countOfVariables } } -@Suppress("INAPPLICABLE_JVM_NAME") +@Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 public abstract class MultivariatePolynomialSpaceOfFractions< C, V, P: Polynomial, R: RationalFunction, > : MultivariateRationalFunctionalSpace, PolynomialSpaceOfFractions() { - @JvmName("VariableRationalFunctionPlus") + @JvmName("plusVariableRational") public override operator fun V.plus(other: R): R = constructRationalFunction( this * other.denominator + other.numerator, other.denominator ) - @JvmName("VariableRationalFunctionMinus") + @JvmName("minusVariableRational") public override operator fun V.minus(other: R): R = constructRationalFunction( this * other.denominator - other.numerator, other.denominator ) - @JvmName("VariableRationalFunctionTimes") + @JvmName("timesVariableRational") public override operator fun V.times(other: R): R = constructRationalFunction( this * other.numerator, other.denominator ) - @JvmName("RationalFunctionVariablePlus") + @JvmName("plusRationalVariable") public override operator fun R.plus(other: V): R = constructRationalFunction( numerator + denominator * other, denominator ) - @JvmName("RationalFunctionVariableMinus") + @JvmName("minusRationalVariable") public override operator fun R.minus(other: V): R = constructRationalFunction( numerator - denominator * other, denominator ) - @JvmName("RationalFunctionVariableTimes") + @JvmName("timesRationalVariable") public override operator fun R.times(other: V): R = constructRationalFunction( numerator * other, diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt index fa97d6a6c..b40aa4775 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt @@ -18,9 +18,9 @@ import space.kscience.kmath.operations.* * @return product of the multiplicand [arg] and the multiplier [multiplier]. * @author Gleb Minaev */ -internal fun Group.multiplyBySquaring(arg: C, multiplier: Int): C = - if (multiplier >= 0) multiplyBySquaring(arg, multiplier.toUInt()) - else multiplyBySquaring(-arg, (-multiplier).toUInt()) +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 /** @@ -32,9 +32,9 @@ internal fun Group.multiplyBySquaring(arg: C, multiplier: Int): C = * @return sum of the augend [base] and product of the multiplicand [arg] and the multiplier [multiplier]. * @author Gleb Minaev */ -internal fun GroupOps.addMultipliedBySquaring(base: C, arg: C, multiplier: Int): C = - if (multiplier >= 0) addMultipliedBySquaring(base, arg, multiplier.toUInt()) - else addMultipliedBySquaring(base, -arg, (-multiplier).toUInt()) +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 /** @@ -47,12 +47,12 @@ internal fun GroupOps.addMultipliedBySquaring(base: C, arg: C, multiplier * @return product of the multiplicand [arg] and the multiplier [multiplier]. * @author Gleb Minaev */ -internal tailrec fun Group.multiplyBySquaring(arg: C, multiplier: UInt): C = +internal tailrec fun Group.multiplyByDoubling(arg: C, multiplier: UInt): C = when { multiplier == 0u -> zero multiplier == 1u -> arg - multiplier and 1u == 0u -> multiplyBySquaring(arg + arg, multiplier shr 1) - multiplier and 1u == 1u -> addMultipliedBySquaring(arg, arg + arg, multiplier shr 1) + 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") } @@ -68,12 +68,12 @@ internal tailrec fun Group.multiplyBySquaring(arg: C, multiplier: UInt): * @return sum of the augend [base] and product of the multiplicand [arg] and the multiplier [multiplier]. * @author Gleb Minaev */ -internal tailrec fun GroupOps.addMultipliedBySquaring(base: C, arg: C, multiplier: UInt): C = +internal tailrec fun GroupOps.addMultipliedByDoubling(base: C, arg: C, multiplier: UInt): C = when { multiplier == 0u -> base multiplier == 1u -> base + arg - multiplier and 1u == 0u -> addMultipliedBySquaring(base, arg + arg, multiplier shr 1) - multiplier and 1u == 1u -> addMultipliedBySquaring(base + arg, arg + arg, multiplier shr 1) + 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") } @@ -86,9 +86,9 @@ internal tailrec fun GroupOps.addMultipliedBySquaring(base: C, arg: C, mu * @return [arg] raised to the power [exponent]. * @author Gleb Minaev */ -internal fun Field.exponentiationBySquaring(arg: C, exponent: Int): C = - if (exponent >= 0) exponentiationBySquaring(arg, exponent.toUInt()) - else exponentiationBySquaring(one / arg, (-exponent).toUInt()) +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 /** @@ -100,9 +100,9 @@ internal fun Field.exponentiationBySquaring(arg: C, exponent: Int): C = * @return product of [base] and [arg] raised to the power [exponent]. * @author Gleb Minaev */ -internal fun Field.multiplyExponentiationBySquaring(base: C, arg: C, exponent: Int): C = - if (exponent >= 0) multiplyExponentiationBySquaring(base, arg, exponent.toUInt()) - else multiplyExponentiationBySquaring(base, one / arg, (-exponent).toUInt()) +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 /** @@ -115,12 +115,12 @@ internal fun Field.multiplyExponentiationBySquaring(base: C, arg: C, expo * @return [arg] raised to the power [exponent]. * @author Gleb Minaev */ -internal tailrec fun Ring.exponentiationBySquaring(arg: C, exponent: UInt): C = +internal tailrec fun Ring.exponentiateBySquaring(arg: C, exponent: UInt): C = when { exponent == 0u -> zero exponent == 1u -> arg - exponent and 1u == 0u -> exponentiationBySquaring(arg * arg, exponent shr 1) - exponent and 1u == 1u -> multiplyExponentiationBySquaring(arg, arg * arg, exponent shr 1) + 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") } @@ -136,11 +136,11 @@ internal tailrec fun Ring.exponentiationBySquaring(arg: C, exponent: UInt * @return product of [base] and [arg] raised to the power [exponent]. * @author Gleb Minaev */ -internal tailrec fun RingOps.multiplyExponentiationBySquaring(base: C, arg: C, exponent: UInt): C = +internal tailrec fun RingOps.multiplyExponentiatedBySquaring(base: C, arg: C, exponent: UInt): C = when { exponent == 0u -> base exponent == 1u -> base * arg - exponent and 1u == 0u -> multiplyExponentiationBySquaring(base, arg * arg, exponent shr 1) - exponent and 1u == 1u -> multiplyExponentiationBySquaring(base * arg, arg * arg, exponent shr 1) + 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-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt index 88d357413..af918b9ae 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt @@ -271,7 +271,7 @@ public fun > LabeledPolynomial.derivativeWithRespectTo( } } }, - multiplyBySquaring(c, degs[variable]!!) + multiplyByDoubling(c, degs[variable]!!) ) } } @@ -302,7 +302,7 @@ public fun > LabeledPolynomial.derivativeWithRespectTo( } } }, - cleanedVariables.fold(c) { acc, variable -> multiplyBySquaring(acc, degs[variable]!!) } + cleanedVariables.fold(c) { acc, variable -> multiplyByDoubling(acc, degs[variable]!!) } ) } } @@ -335,7 +335,7 @@ public fun > LabeledPolynomial.nthDerivativeWithRespectTo( }, degs[variable]!!.let { deg -> (deg downTo deg - order + 1u) - .fold(c) { acc, ord -> multiplyBySquaring(acc, ord) } + .fold(c) { acc, ord -> multiplyByDoubling(acc, ord) } } ) } @@ -371,7 +371,7 @@ public fun > LabeledPolynomial.nthDerivativeWithRespectTo( filteredVariablesAndOrders.entries.fold(c) { acc1, (index, order) -> degs[index]!!.let { deg -> (deg downTo deg - order + 1u) - .fold(acc1) { acc2, ord -> multiplyBySquaring(acc2, ord) } + .fold(acc1) { acc2, ord -> multiplyByDoubling(acc2, ord) } } } ) @@ -398,7 +398,7 @@ public fun > LabeledPolynomial.antiderivativeWithRespectTo( } put( newDegs, - c / multiplyBySquaring(one, newDegs[variable]!!) + c / multiplyByDoubling(one, newDegs[variable]!!) ) } } @@ -425,7 +425,7 @@ public fun > LabeledPolynomial.antiderivativeWithRespectTo( } put( newDegs, - cleanedVariables.fold(c) { acc, variable -> acc / multiplyBySquaring(one, newDegs[variable]!!) } + cleanedVariables.fold(c) { acc, variable -> acc / multiplyByDoubling(one, newDegs[variable]!!) } ) } } @@ -454,7 +454,7 @@ public fun > LabeledPolynomial.nthAntiderivativeWithRespectTo newDegs, newDegs[variable]!!.let { deg -> (deg downTo deg - order + 1u) - .fold(c) { acc, ord -> acc / multiplyBySquaring(one, ord) } + .fold(c) { acc, ord -> acc / multiplyByDoubling(one, ord) } } ) } @@ -485,7 +485,7 @@ public fun > LabeledPolynomial.nthAntiderivativeWithRespectTo filteredVariablesAndOrders.entries.fold(c) { acc1, (index, order) -> newDegs[index]!!.let { deg -> (deg downTo deg - order + 1u) - .fold(acc1) { acc2, ord -> acc2 / multiplyBySquaring(one, ord) } + .fold(acc1) { acc2, ord -> acc2 / multiplyByDoubling(one, ord) } } } ) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt index ee85b0f56..ad817c7ba 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt @@ -322,7 +322,7 @@ public fun > NumberedPolynomial.derivativeWithRespectTo( else -> return@forEach } }.cleanUp(), - multiplyBySquaring(c, degs[variable]) + multiplyByDoubling(c, degs[variable]) ) } } @@ -353,7 +353,7 @@ public fun > NumberedPolynomial.derivativeWithRespectTo( else -> return@forEach } }.cleanUp(), - cleanedVariables.fold(c) { acc, variable -> multiplyBySquaring(acc, degs[variable]) } + cleanedVariables.fold(c) { acc, variable -> multiplyByDoubling(acc, degs[variable]) } ) } } @@ -385,7 +385,7 @@ public fun > NumberedPolynomial.nthDerivativeWithRespectTo( }.cleanUp(), degs[variable].let { deg -> (deg downTo deg - order + 1u) - .fold(c) { acc, ord -> multiplyBySquaring(acc, ord) } + .fold(c) { acc, ord -> multiplyByDoubling(acc, ord) } } ) } @@ -418,7 +418,7 @@ public fun > NumberedPolynomial.nthDerivativeWithRespectTo( filteredVariablesAndOrders.entries.fold(c) { acc1, (index, order) -> degs[index].let { deg -> (deg downTo deg - order + 1u) - .fold(acc1) { acc2, ord -> multiplyBySquaring(acc2, ord) } + .fold(acc1) { acc2, ord -> multiplyByDoubling(acc2, ord) } } } ) @@ -441,7 +441,7 @@ public fun > NumberedPolynomial.antiderivativeWithRespectTo( .forEach { (degs, c) -> put( List(max(variable + 1, degs.size)) { if (it != variable) degs[it] else degs[it] + 1u }, - c / multiplyBySquaring(one, degs[variable]) + c / multiplyByDoubling(one, degs[variable]) ) } } @@ -465,7 +465,7 @@ public fun > NumberedPolynomial.antiderivativeWithRespectTo( .forEach { (degs, c) -> put( List(max(maxRespectedVariable + 1, degs.size)) { if (it !in variables) degs[it] else degs[it] + 1u }, - cleanedVariables.fold(c) { acc, variable -> acc / multiplyBySquaring(one, degs[variable]) } + cleanedVariables.fold(c) { acc, variable -> acc / multiplyByDoubling(one, degs[variable]) } ) } } @@ -490,7 +490,7 @@ public fun > NumberedPolynomial.nthAntiderivativeWithRespectT List(max(variable + 1, degs.size)) { if (it != variable) degs[it] else degs[it] + order }, degs[variable].let { deg -> (deg downTo deg - order + 1u) - .fold(c) { acc, ord -> acc / multiplyBySquaring(one, ord) } + .fold(c) { acc, ord -> acc / multiplyByDoubling(one, ord) } } ) } @@ -518,7 +518,7 @@ public fun > NumberedPolynomial.nthAntiderivativeWithRespectT filteredVariablesAndOrders.entries.fold(c) { acc1, (index, order) -> degs[index].let { deg -> (deg downTo deg - order + 1u) - .fold(acc1) { acc2, ord -> acc2 / multiplyBySquaring(one, ord) } + .fold(acc1) { acc2, ord -> acc2 / multiplyByDoubling(one, ord) } } } ) diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt index fe4a82f11..487cd9ee1 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt @@ -31,47 +31,47 @@ class AlgebraicStubTest { ExprRing { assertEquals( "57", - addMultipliedBySquaring(Expr("57"), Expr("179"), 0u).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), 0u).expr, "tried addMultipliedBySquaring(57, 179, 0u)" ) assertEquals( "(57 + 179)", - addMultipliedBySquaring(Expr("57"), Expr("179"), 1u).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), 1u).expr, "tried addMultipliedBySquaring(57, 179, 1u)" ) assertEquals( "(57 + (179 + 179))", - addMultipliedBySquaring(Expr("57"), Expr("179"), 2u).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), 2u).expr, "tried addMultipliedBySquaring(57, 179, 2u)" ) assertEquals( "((57 + 179) + (179 + 179))", - addMultipliedBySquaring(Expr("57"), Expr("179"), 3u).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), 3u).expr, "tried addMultipliedBySquaring(57, 179, 3u)" ) assertEquals( "(57 + ((179 + 179) + (179 + 179)))", - addMultipliedBySquaring(Expr("57"), Expr("179"), 4u).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), 4u).expr, "tried addMultipliedBySquaring(57, 179, 4u)" ) assertEquals( "((57 + 179) + ((179 + 179) + (179 + 179)))", - addMultipliedBySquaring(Expr("57"), Expr("179"), 5u).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), 5u).expr, "tried addMultipliedBySquaring(57, 179, 5u)" ) assertEquals( "((57 + (179 + 179)) + ((179 + 179) + (179 + 179)))", - addMultipliedBySquaring(Expr("57"), Expr("179"), 6u).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), 6u).expr, "tried addMultipliedBySquaring(57, 179, 6u)" ) assertEquals( "(((57 + 179) + (179 + 179)) + ((179 + 179) + (179 + 179)))", - addMultipliedBySquaring(Expr("57"), Expr("179"), 7u).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), 7u).expr, "tried addMultipliedBySquaring(57, 179, 7u)" ) assertEquals( "(57 + (((179 + 179) + (179 + 179)) + ((179 + 179) + (179 + 179))))", - addMultipliedBySquaring(Expr("57"), Expr("179"), 8u).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), 8u).expr, "tried addMultipliedBySquaring(57, 179, 8u)" ) } @@ -81,47 +81,47 @@ class AlgebraicStubTest { ExprRing { assertEquals( "0", - multiplyBySquaring(Expr("57"), 0u).expr, + multiplyByDoubling(Expr("57"), 0u).expr, "tried multiplyBySquaring(57, 0u)" ) assertEquals( "57", - multiplyBySquaring(Expr("57"), 1u).expr, + multiplyByDoubling(Expr("57"), 1u).expr, "tried multiplyBySquaring(57, 1u)" ) assertEquals( "(57 + 57)", - multiplyBySquaring(Expr("57"), 2u).expr, + multiplyByDoubling(Expr("57"), 2u).expr, "tried multiplyBySquaring(57, 2u)" ) assertEquals( "(57 + (57 + 57))", - multiplyBySquaring(Expr("57"), 3u).expr, + multiplyByDoubling(Expr("57"), 3u).expr, "tried multiplyBySquaring(57, 3u)" ) assertEquals( "((57 + 57) + (57 + 57))", - multiplyBySquaring(Expr("57"), 4u).expr, + multiplyByDoubling(Expr("57"), 4u).expr, "tried multiplyBySquaring(57, 4u)" ) assertEquals( "(57 + ((57 + 57) + (57 + 57)))", - multiplyBySquaring(Expr("57"), 5u).expr, + multiplyByDoubling(Expr("57"), 5u).expr, "tried multiplyBySquaring(57, 5u)" ) assertEquals( "((57 + 57) + ((57 + 57) + (57 + 57)))", - multiplyBySquaring(Expr("57"), 6u).expr, + multiplyByDoubling(Expr("57"), 6u).expr, "tried multiplyBySquaring(57, 6u)" ) assertEquals( "((57 + (57 + 57)) + ((57 + 57) + (57 + 57)))", - multiplyBySquaring(Expr("57"), 7u).expr, + multiplyByDoubling(Expr("57"), 7u).expr, "tried multiplyBySquaring(57, 7u)" ) assertEquals( "(((57 + 57) + (57 + 57)) + ((57 + 57) + (57 + 57)))", - multiplyBySquaring(Expr("57"), 8u).expr, + multiplyByDoubling(Expr("57"), 8u).expr, "tried multiplyBySquaring(57, 8u)" ) } @@ -131,87 +131,87 @@ class AlgebraicStubTest { ExprRing { assertEquals( "57", - addMultipliedBySquaring(Expr("57"), Expr("179"), 0).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), 0).expr, "tried addMultipliedBySquaring(57, 179, 0)" ) assertEquals( "(57 + 179)", - addMultipliedBySquaring(Expr("57"), Expr("179"), 1).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), 1).expr, "tried addMultipliedBySquaring(57, 179, 1)" ) assertEquals( "(57 + -179)", - addMultipliedBySquaring(Expr("57"), Expr("179"), -1).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), -1).expr, "tried addMultipliedBySquaring(57, 179, -1)" ) assertEquals( "(57 + (179 + 179))", - addMultipliedBySquaring(Expr("57"), Expr("179"), 2).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), 2).expr, "tried addMultipliedBySquaring(57, 179, 2)" ) assertEquals( "(57 + (-179 + -179))", - addMultipliedBySquaring(Expr("57"), Expr("179"), -2).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), -2).expr, "tried addMultipliedBySquaring(57, 179, -2)" ) assertEquals( "((57 + 179) + (179 + 179))", - addMultipliedBySquaring(Expr("57"), Expr("179"), 3).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), 3).expr, "tried addMultipliedBySquaring(57, 179, 3)" ) assertEquals( "((57 + -179) + (-179 + -179))", - addMultipliedBySquaring(Expr("57"), Expr("179"), -3).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), -3).expr, "tried addMultipliedBySquaring(57, 179, -3)" ) assertEquals( "(57 + ((179 + 179) + (179 + 179)))", - addMultipliedBySquaring(Expr("57"), Expr("179"), 4).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), 4).expr, "tried addMultipliedBySquaring(57, 179, 4)" ) assertEquals( "(57 + ((-179 + -179) + (-179 + -179)))", - addMultipliedBySquaring(Expr("57"), Expr("179"), -4).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), -4).expr, "tried addMultipliedBySquaring(57, 179, -4)" ) assertEquals( "((57 + 179) + ((179 + 179) + (179 + 179)))", - addMultipliedBySquaring(Expr("57"), Expr("179"), 5).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), 5).expr, "tried addMultipliedBySquaring(57, 179, 5)" ) assertEquals( "((57 + -179) + ((-179 + -179) + (-179 + -179)))", - addMultipliedBySquaring(Expr("57"), Expr("179"), -5).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), -5).expr, "tried addMultipliedBySquaring(57, 179, -5)" ) assertEquals( "((57 + (179 + 179)) + ((179 + 179) + (179 + 179)))", - addMultipliedBySquaring(Expr("57"), Expr("179"), 6).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), 6).expr, "tried addMultipliedBySquaring(57, 179, 6)" ) assertEquals( "((57 + (-179 + -179)) + ((-179 + -179) + (-179 + -179)))", - addMultipliedBySquaring(Expr("57"), Expr("179"), -6).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), -6).expr, "tried addMultipliedBySquaring(57, 179, -6)" ) assertEquals( "(((57 + 179) + (179 + 179)) + ((179 + 179) + (179 + 179)))", - addMultipliedBySquaring(Expr("57"), Expr("179"), 7).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), 7).expr, "tried addMultipliedBySquaring(57, 179, 7)" ) assertEquals( "(((57 + -179) + (-179 + -179)) + ((-179 + -179) + (-179 + -179)))", - addMultipliedBySquaring(Expr("57"), Expr("179"), -7).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), -7).expr, "tried addMultipliedBySquaring(57, 179, -7)" ) assertEquals( "(57 + (((179 + 179) + (179 + 179)) + ((179 + 179) + (179 + 179))))", - addMultipliedBySquaring(Expr("57"), Expr("179"), 8).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), 8).expr, "tried addMultipliedBySquaring(57, 179, 8)" ) assertEquals( "(57 + (((-179 + -179) + (-179 + -179)) + ((-179 + -179) + (-179 + -179))))", - addMultipliedBySquaring(Expr("57"), Expr("179"), -8).expr, + addMultipliedByDoubling(Expr("57"), Expr("179"), -8).expr, "tried addMultipliedBySquaring(57, 179, -8)" ) } @@ -221,87 +221,87 @@ class AlgebraicStubTest { ExprRing { assertEquals( "0", - multiplyBySquaring(Expr("57"), 0).expr, + multiplyByDoubling(Expr("57"), 0).expr, "tried multiplyBySquaring(57, 0)" ) assertEquals( "57", - multiplyBySquaring(Expr("57"), 1).expr, + multiplyByDoubling(Expr("57"), 1).expr, "tried multiplyBySquaring(57, 1)" ) assertEquals( "-57", - multiplyBySquaring(Expr("57"), -1).expr, + multiplyByDoubling(Expr("57"), -1).expr, "tried multiplyBySquaring(57, -1)" ) assertEquals( "(57 + 57)", - multiplyBySquaring(Expr("57"), 2).expr, + multiplyByDoubling(Expr("57"), 2).expr, "tried multiplyBySquaring(57, 2)" ) assertEquals( "(-57 + -57)", - multiplyBySquaring(Expr("57"), -2).expr, + multiplyByDoubling(Expr("57"), -2).expr, "tried multiplyBySquaring(57, -2)" ) assertEquals( "(57 + (57 + 57))", - multiplyBySquaring(Expr("57"), 3).expr, + multiplyByDoubling(Expr("57"), 3).expr, "tried multiplyBySquaring(57, 3)" ) assertEquals( "(-57 + (-57 + -57))", - multiplyBySquaring(Expr("57"), -3).expr, + multiplyByDoubling(Expr("57"), -3).expr, "tried multiplyBySquaring(57, -3)" ) assertEquals( "((57 + 57) + (57 + 57))", - multiplyBySquaring(Expr("57"), 4).expr, + multiplyByDoubling(Expr("57"), 4).expr, "tried multiplyBySquaring(57, 4)" ) assertEquals( "((-57 + -57) + (-57 + -57))", - multiplyBySquaring(Expr("57"), -4).expr, + multiplyByDoubling(Expr("57"), -4).expr, "tried multiplyBySquaring(57, -4)" ) assertEquals( "(57 + ((57 + 57) + (57 + 57)))", - multiplyBySquaring(Expr("57"), 5).expr, + multiplyByDoubling(Expr("57"), 5).expr, "tried multiplyBySquaring(57, 5)" ) assertEquals( "(-57 + ((-57 + -57) + (-57 + -57)))", - multiplyBySquaring(Expr("57"), -5).expr, + multiplyByDoubling(Expr("57"), -5).expr, "tried multiplyBySquaring(57, -5)" ) assertEquals( "((57 + 57) + ((57 + 57) + (57 + 57)))", - multiplyBySquaring(Expr("57"), 6).expr, + multiplyByDoubling(Expr("57"), 6).expr, "tried multiplyBySquaring(57, 6)" ) assertEquals( "((-57 + -57) + ((-57 + -57) + (-57 + -57)))", - multiplyBySquaring(Expr("57"), -6).expr, + multiplyByDoubling(Expr("57"), -6).expr, "tried multiplyBySquaring(57, -6)" ) assertEquals( "((57 + (57 + 57)) + ((57 + 57) + (57 + 57)))", - multiplyBySquaring(Expr("57"), 7).expr, + multiplyByDoubling(Expr("57"), 7).expr, "tried multiplyBySquaring(57, 7)" ) assertEquals( "((-57 + (-57 + -57)) + ((-57 + -57) + (-57 + -57)))", - multiplyBySquaring(Expr("57"), -7).expr, + multiplyByDoubling(Expr("57"), -7).expr, "tried multiplyBySquaring(57, -7)" ) assertEquals( "(((57 + 57) + (57 + 57)) + ((57 + 57) + (57 + 57)))", - multiplyBySquaring(Expr("57"), 8).expr, + multiplyByDoubling(Expr("57"), 8).expr, "tried multiplyBySquaring(57, 8)" ) assertEquals( "(((-57 + -57) + (-57 + -57)) + ((-57 + -57) + (-57 + -57)))", - multiplyBySquaring(Expr("57"), -8).expr, + multiplyByDoubling(Expr("57"), -8).expr, "tried multiplyBySquaring(57, -8)" ) } @@ -311,47 +311,47 @@ class AlgebraicStubTest { ExprRing { assertEquals( "57", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 0u).expr, + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 0u).expr, "tried multiplyExponentiationBySquaring(57, 179, 0u)" ) assertEquals( "(57 * 179)", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 1u).expr, + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 1u).expr, "tried multiplyExponentiationBySquaring(57, 179, 1u)" ) assertEquals( "(57 * (179 * 179))", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 2u).expr, + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 2u).expr, "tried multiplyExponentiationBySquaring(57, 179, 2u)" ) assertEquals( "((57 * 179) * (179 * 179))", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 3u).expr, + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 3u).expr, "tried multiplyExponentiationBySquaring(57, 179, 3u)" ) assertEquals( "(57 * ((179 * 179) * (179 * 179)))", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 4u).expr, + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 4u).expr, "tried multiplyExponentiationBySquaring(57, 179, 4u)" ) assertEquals( "((57 * 179) * ((179 * 179) * (179 * 179)))", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 5u).expr, + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 5u).expr, "tried multiplyExponentiationBySquaring(57, 179, 5u)" ) assertEquals( "((57 * (179 * 179)) * ((179 * 179) * (179 * 179)))", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 6u).expr, + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 6u).expr, "tried multiplyExponentiationBySquaring(57, 179, 6u)" ) assertEquals( "(((57 * 179) * (179 * 179)) * ((179 * 179) * (179 * 179)))", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 7u).expr, + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 7u).expr, "tried multiplyExponentiationBySquaring(57, 179, 7u)" ) assertEquals( "(57 * (((179 * 179) * (179 * 179)) * ((179 * 179) * (179 * 179))))", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 8u).expr, + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 8u).expr, "tried multiplyExponentiationBySquaring(57, 179, 8u)" ) } @@ -361,47 +361,47 @@ class AlgebraicStubTest { ExprRing { assertEquals( "0", - exponentiationBySquaring(Expr("57"), 0u).expr, + exponentiateBySquaring(Expr("57"), 0u).expr, "tried exponentiationBySquaring(57, 0u)" ) assertEquals( "57", - exponentiationBySquaring(Expr("57"), 1u).expr, + exponentiateBySquaring(Expr("57"), 1u).expr, "tried exponentiationBySquaring(57, 1u)" ) assertEquals( "(57 * 57)", - exponentiationBySquaring(Expr("57"), 2u).expr, + exponentiateBySquaring(Expr("57"), 2u).expr, "tried exponentiationBySquaring(57, 2u)" ) assertEquals( "(57 * (57 * 57))", - exponentiationBySquaring(Expr("57"), 3u).expr, + exponentiateBySquaring(Expr("57"), 3u).expr, "tried exponentiationBySquaring(57, 3u)" ) assertEquals( "((57 * 57) * (57 * 57))", - exponentiationBySquaring(Expr("57"), 4u).expr, + exponentiateBySquaring(Expr("57"), 4u).expr, "tried exponentiationBySquaring(57, 4u)" ) assertEquals( "(57 * ((57 * 57) * (57 * 57)))", - exponentiationBySquaring(Expr("57"), 5u).expr, + exponentiateBySquaring(Expr("57"), 5u).expr, "tried exponentiationBySquaring(57, 5u)" ) assertEquals( "((57 * 57) * ((57 * 57) * (57 * 57)))", - exponentiationBySquaring(Expr("57"), 6u).expr, + exponentiateBySquaring(Expr("57"), 6u).expr, "tried exponentiationBySquaring(57, 6u)" ) assertEquals( "((57 * (57 * 57)) * ((57 * 57) * (57 * 57)))", - exponentiationBySquaring(Expr("57"), 7u).expr, + exponentiateBySquaring(Expr("57"), 7u).expr, "tried exponentiationBySquaring(57, 7u)" ) assertEquals( "(((57 * 57) * (57 * 57)) * ((57 * 57) * (57 * 57)))", - exponentiationBySquaring(Expr("57"), 8u).expr, + exponentiateBySquaring(Expr("57"), 8u).expr, "tried exponentiationBySquaring(57, 8u)" ) } @@ -411,87 +411,87 @@ class AlgebraicStubTest { ExprRing { assertEquals( "57", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 0).expr, + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 0).expr, "tried multiplyExponentiationBySquaring(57, 179, 0)" ) assertEquals( "(57 * 179)", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 1).expr, + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 1).expr, "tried multiplyExponentiationBySquaring(57, 179, 1)" ) assertEquals( "(57 * (1 / 179))", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), -1).expr, + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), -1).expr, "tried multiplyExponentiationBySquaring(57, 179, -1)" ) assertEquals( "(57 * (179 * 179))", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 2).expr, + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 2).expr, "tried multiplyExponentiationBySquaring(57, 179, 2)" ) assertEquals( "(57 * ((1 / 179) * (1 / 179)))", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), -2).expr, + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), -2).expr, "tried multiplyExponentiationBySquaring(57, 179, -2)" ) assertEquals( "((57 * 179) * (179 * 179))", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 3).expr, + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 3).expr, "tried multiplyExponentiationBySquaring(57, 179, 3)" ) assertEquals( "((57 * (1 / 179)) * ((1 / 179) * (1 / 179)))", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), -3).expr, + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), -3).expr, "tried multiplyExponentiationBySquaring(57, 179, -3)" ) assertEquals( "(57 * ((179 * 179) * (179 * 179)))", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 4).expr, + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 4).expr, "tried multiplyExponentiationBySquaring(57, 179, 4)" ) assertEquals( "(57 * (((1 / 179) * (1 / 179)) * ((1 / 179) * (1 / 179))))", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), -4).expr, + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), -4).expr, "tried multiplyExponentiationBySquaring(57, 179, -4)" ) assertEquals( "((57 * 179) * ((179 * 179) * (179 * 179)))", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 5).expr, + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 5).expr, "tried multiplyExponentiationBySquaring(57, 179, 5)" ) assertEquals( "((57 * (1 / 179)) * (((1 / 179) * (1 / 179)) * ((1 / 179) * (1 / 179))))", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), -5).expr, + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), -5).expr, "tried multiplyExponentiationBySquaring(57, 179, -5)" ) assertEquals( "((57 * (179 * 179)) * ((179 * 179) * (179 * 179)))", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 6).expr, + 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))))", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), -6).expr, + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), -6).expr, "tried multiplyExponentiationBySquaring(57, 179, -6)" ) assertEquals( "(((57 * 179) * (179 * 179)) * ((179 * 179) * (179 * 179)))", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 7).expr, + 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))))", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), -7).expr, + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), -7).expr, "tried multiplyExponentiationBySquaring(57, 179, -7)" ) assertEquals( "(57 * (((179 * 179) * (179 * 179)) * ((179 * 179) * (179 * 179))))", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), 8).expr, + 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)))))", - multiplyExponentiationBySquaring(Expr("57"), Expr("179"), -8).expr, + multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), -8).expr, "tried multiplyExponentiationBySquaring(57, 179, -8)" ) } @@ -501,87 +501,87 @@ class AlgebraicStubTest { ExprRing { assertEquals( "0", - exponentiationBySquaring(Expr("57"), 0).expr, + exponentiateBySquaring(Expr("57"), 0).expr, "tried exponentiationBySquaring(57, 0)" ) assertEquals( "57", - exponentiationBySquaring(Expr("57"), 1).expr, + exponentiateBySquaring(Expr("57"), 1).expr, "tried exponentiationBySquaring(57, 1)" ) assertEquals( "(1 / 57)", - exponentiationBySquaring(Expr("57"), -1).expr, + exponentiateBySquaring(Expr("57"), -1).expr, "tried exponentiationBySquaring(57, -1)" ) assertEquals( "(57 * 57)", - exponentiationBySquaring(Expr("57"), 2).expr, + exponentiateBySquaring(Expr("57"), 2).expr, "tried exponentiationBySquaring(57, 2)" ) assertEquals( "((1 / 57) * (1 / 57))", - exponentiationBySquaring(Expr("57"), -2).expr, + exponentiateBySquaring(Expr("57"), -2).expr, "tried exponentiationBySquaring(57, -2)" ) assertEquals( "(57 * (57 * 57))", - exponentiationBySquaring(Expr("57"), 3).expr, + exponentiateBySquaring(Expr("57"), 3).expr, "tried exponentiationBySquaring(57, 3)" ) assertEquals( "((1 / 57) * ((1 / 57) * (1 / 57)))", - exponentiationBySquaring(Expr("57"), -3).expr, + exponentiateBySquaring(Expr("57"), -3).expr, "tried exponentiationBySquaring(57, -3)" ) assertEquals( "((57 * 57) * (57 * 57))", - exponentiationBySquaring(Expr("57"), 4).expr, + exponentiateBySquaring(Expr("57"), 4).expr, "tried exponentiationBySquaring(57, 4)" ) assertEquals( "(((1 / 57) * (1 / 57)) * ((1 / 57) * (1 / 57)))", - exponentiationBySquaring(Expr("57"), -4).expr, + exponentiateBySquaring(Expr("57"), -4).expr, "tried exponentiationBySquaring(57, -4)" ) assertEquals( "(57 * ((57 * 57) * (57 * 57)))", - exponentiationBySquaring(Expr("57"), 5).expr, + exponentiateBySquaring(Expr("57"), 5).expr, "tried exponentiationBySquaring(57, 5)" ) assertEquals( "((1 / 57) * (((1 / 57) * (1 / 57)) * ((1 / 57) * (1 / 57))))", - exponentiationBySquaring(Expr("57"), -5).expr, + exponentiateBySquaring(Expr("57"), -5).expr, "tried exponentiationBySquaring(57, -5)" ) assertEquals( "((57 * 57) * ((57 * 57) * (57 * 57)))", - exponentiationBySquaring(Expr("57"), 6).expr, + exponentiateBySquaring(Expr("57"), 6).expr, "tried exponentiationBySquaring(57, 6)" ) assertEquals( "(((1 / 57) * (1 / 57)) * (((1 / 57) * (1 / 57)) * ((1 / 57) * (1 / 57))))", - exponentiationBySquaring(Expr("57"), -6).expr, + exponentiateBySquaring(Expr("57"), -6).expr, "tried exponentiationBySquaring(57, -6)" ) assertEquals( "((57 * (57 * 57)) * ((57 * 57) * (57 * 57)))", - exponentiationBySquaring(Expr("57"), 7).expr, + exponentiateBySquaring(Expr("57"), 7).expr, "tried exponentiationBySquaring(57, 7)" ) assertEquals( "(((1 / 57) * ((1 / 57) * (1 / 57))) * (((1 / 57) * (1 / 57)) * ((1 / 57) * (1 / 57))))", - exponentiationBySquaring(Expr("57"), -7).expr, + exponentiateBySquaring(Expr("57"), -7).expr, "tried exponentiationBySquaring(57, -7)" ) assertEquals( "(((57 * 57) * (57 * 57)) * ((57 * 57) * (57 * 57)))", - exponentiationBySquaring(Expr("57"), 8).expr, + 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))))", - exponentiationBySquaring(Expr("57"), -8).expr, + exponentiateBySquaring(Expr("57"), -8).expr, "tried exponentiationBySquaring(57, -8)" ) } -- 2.34.1 From 9b51062bf7c8b7d65f93120ac36a87bc6731742e Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sat, 11 Jun 2022 16:09:24 +0300 Subject: [PATCH 074/275] Sift. --- .../kmath/functions/LabeledPolynomial.kt | 539 ------------------ .../functions/LabeledRationalFunction.kt | 139 ----- .../kmath/functions/ListPolynomial.kt | 367 ------------ .../kmath/functions/ListRationalFunction.kt | 105 ---- .../kmath/functions/NumberedPolynomial.kt | 389 ------------- .../functions/NumberedRationalFunction.kt | 188 ------ .../kscience/kmath/functions/Piecewise.kt | 132 ----- .../kmath/functions/labeledConstructors.kt | 203 ------- .../kmath/functions/labeledPolynomialUtil.kt | 495 ---------------- .../functions/labeledRationalFunctionUtil.kt | 33 -- .../kmath/functions/listConstructors.kt | 60 -- .../kmath/functions/listPolynomialUtil.kt | 233 -------- .../functions/listRationalFunctionUtil.kt | 221 ------- .../kmath/functions/numberedConstructors.kt | 195 ------- .../kmath/functions/numberedPolynomialUtil.kt | 528 ----------------- .../functions/numberedRationalFunctionUtil.kt | 33 -- .../kmath/integration/SplineIntegrator.kt | 107 ---- .../kmath/functions/ListPolynomialTest.kt | 491 ---------------- .../kmath/functions/ListPolynomialUtilTest.kt | 257 --------- 19 files changed, 4715 deletions(-) delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listRationalFunctionUtil.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt deleted file mode 100644 index b904f7331..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ /dev/null @@ -1,539 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.ScaleOperations -import kotlin.math.max - - -/** - * Represents multivariate polynomials with labeled variables. - * - * @param C Ring in which the polynomial is considered. - */ -public data class LabeledPolynomial -internal constructor( - /** - * Map that collects coefficients of the polynomial. Every non-zero monomial - * `a x_1^{d_1} ... x_n^{d_n}` is represented as pair "key-value" in the map, where value is coefficients `a` and - * key is map that associates variables in the monomial with multiplicity of them occurring in the monomial. - * For example polynomial - * ``` - * 5 a^2 c^3 - 6 b + 0 b c - * ``` - * has coefficients represented as - * ``` - * mapOf( - * mapOf( - * a to 2, - * c to 3 - * ) to 5, - * mapOf( - * b to 1 - * ) to (-6) - * ) - * ``` - * where `a`, `b` and `c` are corresponding [Symbol] objects. - */ - public val coefficients: Map, C> -) : Polynomial { - override fun toString(): String = "LabeledPolynomial$coefficients" -} - -/** - * Space of polynomials. - * - * @param C the type of operated polynomials. - * @param A the intersection of [Ring] of [C] and [ScaleOperations] of [C]. - * @param ring the [A] instance. - */ -public class LabeledPolynomialSpace>( - public override val ring: A, -) : MultivariatePolynomialSpace>, PolynomialSpaceOverRing, A> { - public override operator fun Symbol.plus(other: Int): LabeledPolynomial = - if (other == 0) LabeledPolynomial(mapOf( - mapOf(this@plus to 1U) to constantOne, - )) - else LabeledPolynomial(mapOf( - mapOf(this@plus to 1U) to constantOne, - emptyMap() to constantOne * other, - )) - public override operator fun Symbol.minus(other: Int): LabeledPolynomial = - if (other == 0) LabeledPolynomial(mapOf( - mapOf(this@minus to 1U) to -constantOne, - )) - else LabeledPolynomial(mapOf( - mapOf(this@minus to 1U) to -constantOne, - emptyMap() to constantOne * other, - )) - public override operator fun Symbol.times(other: Int): LabeledPolynomial = - if (other == 0) zero - else LabeledPolynomial(mapOf( - mapOf(this to 1U) to constantOne * other, - )) - - public override operator fun Int.plus(other: Symbol): LabeledPolynomial = - if (this == 0) LabeledPolynomial(mapOf( - mapOf(other to 1U) to constantOne, - )) - else LabeledPolynomial(mapOf( - mapOf(other to 1U) to constantOne, - emptyMap() to constantOne * this@plus, - )) - public override operator fun Int.minus(other: Symbol): LabeledPolynomial = - if (this == 0) LabeledPolynomial(mapOf( - mapOf(other to 1U) to -constantOne, - )) - else LabeledPolynomial(mapOf( - mapOf(other to 1U) to -constantOne, - emptyMap() to constantOne * this@minus, - )) - public override operator fun Int.times(other: Symbol): LabeledPolynomial = - if (this == 0) zero - else LabeledPolynomial(mapOf( - mapOf(other to 1U) to constantOne * this@times, - )) - - /** - * Returns sum of the polynomial and the integer represented as polynomial. - * - * The operation is equivalent to adding [other] copies of unit polynomial to [this]. - */ - public override operator fun LabeledPolynomial.plus(other: Int): LabeledPolynomial = - if (other == 0) this - else with(coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to other.asConstant())) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = emptyMap() - - this[degs] = getOrElse(degs) { constantZero } + other - } - ) - } - /** - * Returns difference between the polynomial and the integer represented as polynomial. - * - * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. - */ - public override operator fun LabeledPolynomial.minus(other: Int): LabeledPolynomial = - if (other == 0) this - else with(coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to (-other).asConstant())) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = emptyMap() - - this[degs] = getOrElse(degs) { constantZero } - other - } - ) - } - /** - * Returns product of the polynomial and the integer represented as polynomial. - * - * The operation is equivalent to sum of [other] copies of [this]. - */ - public override operator fun LabeledPolynomial.times(other: Int): LabeledPolynomial = - if (other == 0) zero - else LabeledPolynomial( - coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this[degs]!! * other - } - ) - - /** - * Returns sum of the integer represented as 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 = - if (this == 0) other - else with(other.coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@plus.asConstant())) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = emptyMap() - - this[degs] = this@plus + getOrElse(degs) { constantZero } - } - ) - } - /** - * Returns difference between the integer represented as 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 = - if (this == 0) other - else with(other.coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@minus.asConstant())) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = emptyMap() - - this[degs] = this@minus - getOrElse(degs) { constantZero } - } - ) - } - /** - * Returns product of the integer represented as polynomial and the polynomial. - * - * The operation is equivalent to sum of [this] copies of [other]. - */ - public override operator fun Int.times(other: LabeledPolynomial): LabeledPolynomial = - if (this == 0) zero - else LabeledPolynomial( - other.coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this@times * this[degs]!! - } - ) - - /** - * Converts the integer [value] to polynomial. - */ - public override fun number(value: Int): LabeledPolynomial = number(constantNumber(value)) - - public override operator fun C.plus(other: Symbol): LabeledPolynomial = - LabeledPolynomial(mapOf( - mapOf(other to 1U) to constantOne, - emptyMap() to this@plus, - )) - public override operator fun C.minus(other: Symbol): LabeledPolynomial = - LabeledPolynomial(mapOf( - mapOf(other to 1U) to -constantOne, - emptyMap() to this@minus, - )) - public override operator fun C.times(other: Symbol): LabeledPolynomial = - LabeledPolynomial(mapOf( - mapOf(other to 1U) to this@times, - )) - - public override operator fun Symbol.plus(other: C): LabeledPolynomial = - LabeledPolynomial(mapOf( - mapOf(this@plus to 1U) to constantOne, - emptyMap() to other, - )) - public override operator fun Symbol.minus(other: C): LabeledPolynomial = - LabeledPolynomial(mapOf( - mapOf(this@minus to 1U) to -constantOne, - emptyMap() to other, - )) - public override operator fun Symbol.times(other: C): LabeledPolynomial = - LabeledPolynomial(mapOf( - mapOf(this@times to 1U) to other, - )) - - /** - * Returns sum of the constant represented as polynomial and the polynomial. - */ - override operator fun C.plus(other: LabeledPolynomial): LabeledPolynomial = - with(other.coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@plus)) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = emptyMap() - - this[degs] = this@plus + getOrElse(degs) { constantZero } - } - ) - } - /** - * Returns difference between the constant represented as polynomial and the polynomial. - */ - override operator fun C.minus(other: LabeledPolynomial): LabeledPolynomial = - with(other.coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@minus)) - else LabeledPolynomial( - toMutableMap() - .apply { - forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } - - val degs = emptyMap() - - this[degs] = this@minus - getOrElse(degs) { constantZero } - } - ) - } - /** - * Returns product of the constant represented as polynomial and the polynomial. - */ - override operator fun C.times(other: LabeledPolynomial): LabeledPolynomial = - LabeledPolynomial( - other.coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this@times * this[degs]!! - } - ) - - /** - * Returns sum of the constant represented as polynomial and the polynomial. - */ - override operator fun LabeledPolynomial.plus(other: C): LabeledPolynomial = - with(coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to other)) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = emptyMap() - - this[degs] = getOrElse(degs) { constantZero } + other - } - ) - } - /** - * Returns difference between the constant represented as polynomial and the polynomial. - */ - override operator fun LabeledPolynomial.minus(other: C): LabeledPolynomial = - with(coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to other)) - else LabeledPolynomial( - toMutableMap() - .apply { - forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } - - val degs = emptyMap() - - this[degs] = getOrElse(degs) { constantZero } - other - } - ) - } - /** - * Returns product of the constant represented as polynomial and the polynomial. - */ - override operator fun LabeledPolynomial.times(other: C): LabeledPolynomial = - LabeledPolynomial( - coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this[degs]!! * other - } - ) - - /** - * Converts the constant [value] to polynomial. - */ - public override fun number(value: C): LabeledPolynomial = - LabeledPolynomial(mapOf(emptyMap() to value)) - - public override operator fun Symbol.unaryPlus(): LabeledPolynomial = - LabeledPolynomial(mapOf( - mapOf(this to 1U) to constantOne, - )) - public override operator fun Symbol.unaryMinus(): LabeledPolynomial = - LabeledPolynomial(mapOf( - mapOf(this to 1U) to -constantOne, - )) - public override operator fun Symbol.plus(other: Symbol): LabeledPolynomial = - if (this == other) LabeledPolynomial(mapOf( - mapOf(this to 1U) to constantOne * 2 - )) - else LabeledPolynomial(mapOf( - mapOf(this to 1U) to constantOne, - mapOf(other to 1U) to constantOne, - )) - public override operator fun Symbol.minus(other: Symbol): LabeledPolynomial = - if (this == other) zero - else LabeledPolynomial(mapOf( - mapOf(this to 1U) to constantOne, - mapOf(other to 1U) to -constantOne, - )) - public override operator fun Symbol.times(other: Symbol): LabeledPolynomial = - if (this == other) LabeledPolynomial(mapOf( - mapOf(this to 2U) to constantOne - )) - else LabeledPolynomial(mapOf( - mapOf(this to 1U, other to 1U) to constantOne, - )) - - public override operator fun Symbol.plus(other: LabeledPolynomial): LabeledPolynomial = - with(other.coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(mapOf(this@plus to 1u) to constantOne)) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = mapOf(this@plus to 1U) - - this[degs] = constantOne + getOrElse(degs) { constantZero } - } - ) - } - public override operator fun Symbol.minus(other: LabeledPolynomial): LabeledPolynomial = - with(other.coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(mapOf(this@minus to 1u) to constantOne)) - else LabeledPolynomial( - toMutableMap() - .apply { - forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } - - val degs = mapOf(this@minus to 1U) - - this[degs] = constantOne - getOrElse(degs) { constantZero } - } - ) - } - public override operator fun Symbol.times(other: LabeledPolynomial): LabeledPolynomial = - LabeledPolynomial( - other.coefficients - .mapKeys { (degs, _) -> degs.toMutableMap().also{ it[this] = if (this in it) it[this]!! + 1U else 1U } } - ) - - public override operator fun LabeledPolynomial.plus(other: Symbol): LabeledPolynomial = - with(coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(mapOf(other to 1u) to constantOne)) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = mapOf(other to 1U) - - this[degs] = constantOne + getOrElse(degs) { constantZero } - } - ) - } - public override operator fun LabeledPolynomial.minus(other: Symbol): LabeledPolynomial = - with(coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(mapOf(other to 1u) to constantOne)) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = mapOf(other to 1U) - - this[degs] = constantOne - getOrElse(degs) { constantZero } - } - ) - } - public override operator fun LabeledPolynomial.times(other: Symbol): LabeledPolynomial = - LabeledPolynomial( - coefficients - .mapKeys { (degs, _) -> degs.toMutableMap().also{ it[other] = if (other in it) it[other]!! + 1U else 1U } } - ) - - /** - * Returns negation of the polynomial. - */ - override fun LabeledPolynomial.unaryMinus(): LabeledPolynomial = - LabeledPolynomial( - coefficients.mapValues { -it.value } - ) - /** - * Returns sum of the polynomials. - */ - override operator fun LabeledPolynomial.plus(other: LabeledPolynomial): LabeledPolynomial = - LabeledPolynomial( - buildMap(coefficients.size + other.coefficients.size) { - other.coefficients.mapValuesTo(this) { it.value } - other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value } - } - ) - /** - * Returns difference of the polynomials. - */ - override operator fun LabeledPolynomial.minus(other: LabeledPolynomial): LabeledPolynomial = - LabeledPolynomial( - buildMap(coefficients.size + other.coefficients.size) { - other.coefficients.mapValuesTo(this) { it.value } - other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value } - } - ) - /** - * Returns product of the polynomials. - */ - override operator fun LabeledPolynomial.times(other: LabeledPolynomial): LabeledPolynomial = - LabeledPolynomial( - buildMap(coefficients.size * other.coefficients.size) { - for ((degs1, c1) in coefficients) for ((degs2, c2) in other.coefficients) { - val degs = degs1.toMutableMap() - degs2.mapValuesTo(degs) { (variable, deg) -> degs.getOrElse(variable) { 0u } + deg } - val c = c1 * c2 - this[degs] = if (degs in this) this[degs]!! + c else c - } - } - ) - - /** - * Instance of zero polynomial (zero of the polynomial ring). - */ - override val zero: LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to constantZero)) - /** - * Instance of unit polynomial (unit of the polynomial ring). - */ - override val one: LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to constantOne)) - - /** - * 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, c) -> 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.entries.forEach { (degs, _) -> - degs.mapValuesTo(this) { (variable, deg) -> - max(getOrElse(variable) { 0u }, deg) - } - } - } - /** - * 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 - -// @Suppress("NOTHING_TO_INLINE") -// public inline fun LabeledPolynomial.substitute(argument: Map): LabeledPolynomial = this.substitute(ring, argument) -// @Suppress("NOTHING_TO_INLINE") -// @JvmName("substitutePolynomial") -// public inline fun LabeledPolynomial.substitute(argument: Map>): LabeledPolynomial = this.substitute(ring, argument) -// -// @Suppress("NOTHING_TO_INLINE") -// public inline fun LabeledPolynomial.asFunction(): (Map) -> LabeledPolynomial = { this.substitute(ring, it) } -// @Suppress("NOTHING_TO_INLINE") -// public inline fun LabeledPolynomial.asFunctionOnConstants(): (Map) -> LabeledPolynomial = { this.substitute(ring, it) } -// @Suppress("NOTHING_TO_INLINE") -// public inline fun LabeledPolynomial.asFunctionOnPolynomials(): (Map>) -> LabeledPolynomial = { this.substitute(ring, it) } -// -// @Suppress("NOTHING_TO_INLINE") -// public inline operator fun LabeledPolynomial.invoke(argument: Map): LabeledPolynomial = this.substitute(ring, argument) -// @Suppress("NOTHING_TO_INLINE") -// @JvmName("invokePolynomial") -// public inline operator fun LabeledPolynomial.invoke(argument: Map>): LabeledPolynomial = this.substitute(ring, argument) -} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt deleted file mode 100644 index 76c6874f5..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.invoke - - -public class LabeledRationalFunction( - public override val numerator: LabeledPolynomial, - public override val denominator: LabeledPolynomial -) : RationalFunction> { - override fun toString(): String = "LabeledRationalFunction${numerator.coefficients}/${denominator.coefficients}" -} - -public class LabeledRationalFunctionSpace>( - public val ring: A, -) : - MultivariateRationalFunctionalSpaceOverMultivariatePolynomialSpace< - C, - Symbol, - LabeledPolynomial, - LabeledRationalFunction, - LabeledPolynomialSpace, - >, - MultivariatePolynomialSpaceOfFractions< - C, - Symbol, - LabeledPolynomial, - LabeledRationalFunction, - >() { - - override val polynomialRing : LabeledPolynomialSpace = LabeledPolynomialSpace(ring) - override fun constructRationalFunction( - numerator: LabeledPolynomial, - denominator: LabeledPolynomial - ): LabeledRationalFunction = - LabeledRationalFunction(numerator, denominator) - - /** - * Instance of zero rational function (zero of the rational functions ring). - */ - public override val zero: LabeledRationalFunction = LabeledRationalFunction(polynomialZero, polynomialOne) - /** - * Instance of unit polynomial (unit of the rational functions ring). - */ - public override val one: LabeledRationalFunction = LabeledRationalFunction(polynomialOne, polynomialOne) - - // TODO: Разобрать - -// operator fun invoke(arg: Map): LabeledRationalFunction = -// LabeledRationalFunction( -// numerator(arg), -// denominator(arg) -// ) -// -// @JvmName("invokeLabeledPolynomial") -// operator fun invoke(arg: Map>): LabeledRationalFunction = -// LabeledRationalFunction( -// numerator(arg), -// denominator(arg) -// ) -// -// @JvmName("invokeLabeledRationalFunction") -// operator fun invoke(arg: Map>): LabeledRationalFunction { -// var num = numerator invokeRFTakeNumerator arg -// var den = denominator invokeRFTakeNumerator arg -// for (variable in variables) if (variable in arg) { -// val degreeDif = degrees[variable]!! -// if (degreeDif > 0) -// den = multiplyByPower(den, arg[variable]!!.denominator, degreeDif) -// else -// num = multiplyByPower(num, arg[variable]!!.denominator, -degreeDif) -// } -// return LabeledRationalFunction(num, den) -// } -// -// override fun toString(): String = toString(emptyMap()) -// -// fun toString(names: Map = emptyMap()): String = -// when (true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toString(names) -// else -> "${numerator.toStringWithBrackets(names)}/${denominator.toStringWithBrackets(names)}" -// } -// -// fun toString(namer: (Symbol) -> String): String = -// when (true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toString(namer) -// else -> "${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)}" -// } -// -// fun toStringWithBrackets(names: Map = emptyMap()): String = -// when (true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toStringWithBrackets(names) -// else -> "(${numerator.toStringWithBrackets(names)}/${denominator.toStringWithBrackets(names)})" -// } -// -// fun toStringWithBrackets(namer: (Symbol) -> String): String = -// when (true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toStringWithBrackets(namer) -// else -> "(${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)})" -// } -// -// fun toReversedString(names: Map = emptyMap()): String = -// when (true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedString(names) -// else -> "${numerator.toReversedStringWithBrackets(names)}/${denominator.toReversedStringWithBrackets(names)}" -// } -// -// fun toReversedString(namer: (Symbol) -> String): String = -// when (true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedString(namer) -// else -> "${numerator.toReversedStringWithBrackets(namer)}/${denominator.toReversedStringWithBrackets(namer)}" -// } -// -// fun toReversedStringWithBrackets(names: Map = emptyMap()): String = -// when (true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedStringWithBrackets(names) -// else -> "(${numerator.toReversedStringWithBrackets(names)}/${denominator.toReversedStringWithBrackets(names)})" -// } -// -// fun toReversedStringWithBrackets(namer: (Symbol) -> String): String = -// when (true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedStringWithBrackets(namer) -// else -> "(${numerator.toReversedStringWithBrackets(namer)}/${denominator.toReversedStringWithBrackets(namer)})" -// } -} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt deleted file mode 100644 index 585da95ea..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.ScaleOperations -import space.kscience.kmath.operations.invoke -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract -import kotlin.experimental.ExperimentalTypeInference -import kotlin.jvm.JvmName -import kotlin.math.max -import kotlin.math.min - - -/** - * Polynomial model without fixation on specific context they are applied to. - * - * @param coefficients constant is the leftmost coefficient. - */ -public data class ListPolynomial( - /** - * List that collects coefficients of the polynomial. Every monomial `a x^d` is represented as a coefficients - * `a` placed into the list with index `d`. For example coefficients of 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 recommended not to put extra zeros at end of the list (as for `0x^3` and `0x^4` in the example), but is not - * prohibited. - */ - public val coefficients: List -) : Polynomial { - override fun toString(): String = "Polynomial$coefficients" -} - -/** - * Space of univariate 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 open class ListPolynomialSpace>( - public override val ring: A, -) : PolynomialSpaceOverRing, A> { - /** - * Returns sum of the polynomial and the integer represented as 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 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 polynomial. - * - * The operation is equivalent to sum of [other] copies of [this]. - */ - public override operator fun ListPolynomial.times(other: Int): ListPolynomial = - if (other == 0) zero - else ListPolynomial( - coefficients - .toMutableList() - .apply { - for (deg in indices) this[deg] = this[deg] * other - } - ) - - /** - * Returns sum of the integer represented as 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 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 = - if (this == 0) other - else - ListPolynomial( - other.coefficients - .toMutableList() - .apply { - forEachIndexed { index, c -> if (index != 0) this[index] = -c } - - val result = this@minus - getOrElse(0) { constantZero } - - if(size == 0) add(result) - else this[0] = result - } - ) - /** - * Returns product of the integer represented as polynomial and the polynomial. - * - * The operation is equivalent to sum of [this] copies of [other]. - */ - public override operator fun Int.times(other: ListPolynomial): ListPolynomial = - if (this == 0) zero - else ListPolynomial( - other.coefficients - .toMutableList() - .apply { - for (deg in indices) this[deg] = this@times * this[deg] - } - ) - - /** - * Converts the integer [value] to polynomial. - */ - public override fun number(value: Int): ListPolynomial = number(constantNumber(value)) - - /** - * Returns sum of the constant represented as 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 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 { - forEachIndexed { index, c -> if (index != 0) this[index] = -c } - - 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 polynomial and the polynomial. - */ - public override operator fun C.times(other: ListPolynomial): ListPolynomial = - ListPolynomial( - other.coefficients - .toMutableList() - .apply { - for (deg in indices) this[deg] = this@times * this[deg] - } - ) - - /** - * Returns sum of the constant represented as 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 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 polynomial and the polynomial. - */ - public override operator fun ListPolynomial.times(other: C): ListPolynomial = - ListPolynomial( - coefficients - .toMutableList() - .apply { - for (deg in indices) this[deg] = this[deg] * other - } - ) - - /** - * Converts the constant [value] to polynomial. - */ - public override fun number(value: C): ListPolynomial = ListPolynomial(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 } - } - ) - } - - /** - * Instance of zero polynomial (zero of the polynomial ring). - */ - override val zero: ListPolynomial = ListPolynomial(emptyList()) - /** - * Instance of unit constant (unit of the underlying ring). - */ - override val one: ListPolynomial = 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 - - @Suppress("NOTHING_TO_INLINE") - public inline fun ListPolynomial.substitute(argument: C): C = this.substitute(ring, argument) - @Suppress("NOTHING_TO_INLINE") - public inline fun ListPolynomial.substitute(argument: ListPolynomial): ListPolynomial = this.substitute(ring, argument) - - @Suppress("NOTHING_TO_INLINE") - public inline fun ListPolynomial.asFunction(): (C) -> C = { this.substitute(ring, it) } - @Suppress("NOTHING_TO_INLINE") - public inline fun ListPolynomial.asFunctionOnConstants(): (C) -> C = { this.substitute(ring, it) } - @Suppress("NOTHING_TO_INLINE") - public inline fun ListPolynomial.asFunctionOnPolynomials(): (ListPolynomial) -> ListPolynomial = { this.substitute(ring, it) } - - /** - * Evaluates the polynomial for the given value [argument]. - */ - @Suppress("NOTHING_TO_INLINE") - public inline operator fun ListPolynomial.invoke(argument: C): C = this.substitute(ring, argument) - @Suppress("NOTHING_TO_INLINE") - public inline operator fun ListPolynomial.invoke(argument: ListPolynomial): ListPolynomial = this.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-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt deleted file mode 100644 index 7b6c23ac3..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.operations.Ring - - -public data class ListRationalFunction( - public override val numerator: ListPolynomial, - public override val denominator: ListPolynomial -) : RationalFunction> { - override fun toString(): String = "RationalFunction${numerator.coefficients}/${denominator.coefficients}" -} - -public class ListRationalFunctionSpace> ( - public val ring: A, -) : - RationalFunctionalSpaceOverPolynomialSpace< - C, - ListPolynomial, - ListRationalFunction, - ListPolynomialSpace, - >, - PolynomialSpaceOfFractions< - C, - ListPolynomial, - ListRationalFunction, - >() { - - override val polynomialRing : ListPolynomialSpace = ListPolynomialSpace(ring) - override fun constructRationalFunction(numerator: ListPolynomial, denominator: ListPolynomial): ListRationalFunction = - ListRationalFunction(numerator, denominator) - - /** - * Instance of zero rational function (zero of the rational functions ring). - */ - public override val zero: ListRationalFunction = ListRationalFunction(polynomialZero, polynomialOne) - /** - * Instance of unit polynomial (unit of the rational functions ring). - */ - public override val one: ListRationalFunction = ListRationalFunction(polynomialOne, polynomialOne) - - // TODO: Разобрать - -// operator fun invoke(arg: UnivariatePolynomial): RationalFunction = -// RationalFunction( -// numerator(arg), -// denominator(arg) -// ) -// -// operator fun invoke(arg: RationalFunction): RationalFunction { -// val num = numerator invokeRFTakeNumerator arg -// val den = denominator invokeRFTakeNumerator arg -// val degreeDif = numeratorDegree - denominatorDegree -// return if (degreeDif > 0) -// RationalFunction( -// num, -// multiplyByPower(den, arg.denominator, degreeDif) -// ) -// else -// RationalFunction( -// multiplyByPower(num, arg.denominator, -degreeDif), -// den -// ) -// } -// -// override fun toString(): String = toString(UnivariatePolynomial.variableName) -// -// fun toString(withVariableName: String = UnivariatePolynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toString(withVariableName) -// else -> "${numerator.toStringWithBrackets(withVariableName)}/${denominator.toStringWithBrackets(withVariableName)}" -// } -// -// fun toStringWithBrackets(withVariableName: String = UnivariatePolynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toStringWithBrackets(withVariableName) -// else -> "(${numerator.toStringWithBrackets(withVariableName)}/${denominator.toStringWithBrackets(withVariableName)})" -// } -// -// fun toReversedString(withVariableName: String = UnivariatePolynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedString(withVariableName) -// else -> "${numerator.toReversedStringWithBrackets(withVariableName)}/${denominator.toReversedStringWithBrackets(withVariableName)}" -// } -// -// fun toReversedStringWithBrackets(withVariableName: String = UnivariatePolynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedStringWithBrackets(withVariableName) -// else -> "(${numerator.toReversedStringWithBrackets(withVariableName)}/${denominator.toReversedStringWithBrackets(withVariableName)})" -// } -// -// fun removeZeros() = -// RationalFunction( -// numerator.removeZeros(), -// denominator.removeZeros() -// ) -} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt deleted file mode 100644 index e75373819..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.operations.invoke -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.ScaleOperations -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract -import kotlin.experimental.ExperimentalTypeInference -import kotlin.jvm.JvmName -import kotlin.math.max - - -/** - * Polynomial model without fixation on specific context they are applied to. - * - * @param C the type of constants. - */ -public data class NumberedPolynomial -internal constructor( - /** - * Map that collects coefficients of the polynomial. Every monomial `a x_1^{d_1} ... x_n^{d_n}` is represented as - * pair "key-value" in the map, where value is coefficients `a` and - * key is list that associates index of every variable in the monomial with multiplicity of the variable occurring - * in the monomial. For example coefficients of polynomial `5 x_1^2 x_3^3 - 6 x_2` can be represented as - * ``` - * mapOf( - * listOf(2, 0, 3) to 5, - * listOf(0, 1) to (-6), - * ) - * ``` - * and also as - * ``` - * mapOf( - * listOf(2, 0, 3) to 5, - * listOf(0, 1) to (-6), - * listOf(0, 1, 1) to 0, - * ) - * ``` - * It is recommended not to put zero monomials into the map, but is not prohibited. Lists of degrees always do not - * contain any zeros on end, but can contain zeros on start or anywhere in middle. - */ - public val coefficients: Map, C> -) : Polynomial { - override fun toString(): String = "NumberedPolynomial$coefficients" -} - -/** - * Space of polynomials. - * - * @param C the type of operated polynomials. - * @param A the intersection of [Ring] of [C] and [ScaleOperations] of [C]. - * @param ring the [A] instance. - */ -public open class NumberedPolynomialSpace>( - public final override val ring: A, -) : PolynomialSpaceOverRing, A> { - /** - * Returns sum of the polynomial and the integer represented as 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 - NumberedPolynomial( - coefficients - .toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = getOrElse(degs) { constantZero } + other - } - ) - /** - * Returns difference between the polynomial and the integer represented as 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 - NumberedPolynomial( - coefficients - .toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = getOrElse(degs) { constantZero } - other - } - ) - /** - * Returns product of the polynomial and the integer represented as polynomial. - * - * The operation is equivalent to sum of [other] copies of [this]. - */ - public override operator fun NumberedPolynomial.times(other: Int): NumberedPolynomial = - if (other == 0) zero - else NumberedPolynomial( - coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this[degs]!! * other - } - ) - - /** - * Returns sum of the integer represented as 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 - NumberedPolynomial( - other.coefficients - .toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = this@plus + getOrElse(degs) { constantZero } - } - ) - /** - * Returns difference between the integer represented as 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 = - if (this == 0) other - else - NumberedPolynomial( - other.coefficients - .toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = this@minus - getOrElse(degs) { constantZero } - } - ) - /** - * Returns product of the integer represented as polynomial and the polynomial. - * - * The operation is equivalent to sum of [this] copies of [other]. - */ - public override operator fun Int.times(other: NumberedPolynomial): NumberedPolynomial = - if (this == 0) zero - else NumberedPolynomial( - other.coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this@times * this[degs]!! - } - ) - - /** - * Converts the integer [value] to polynomial. - */ - public override fun number(value: Int): NumberedPolynomial = number(constantNumber(value)) - - /** - * Returns sum of the constant represented as polynomial and the polynomial. - */ - override operator fun C.plus(other: NumberedPolynomial): NumberedPolynomial = - with(other.coefficients) { - if (isEmpty()) NumberedPolynomial(mapOf(emptyList() to this@plus)) - else NumberedPolynomial( - toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = this@plus + getOrElse(degs) { constantZero } - } - ) - } - /** - * Returns difference between the constant represented as polynomial and the polynomial. - */ - override operator fun C.minus(other: NumberedPolynomial): NumberedPolynomial = - with(other.coefficients) { - if (isEmpty()) NumberedPolynomial(mapOf(emptyList() to this@minus)) - else NumberedPolynomial( - toMutableMap() - .apply { - forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } - - val degs = emptyList() - - this[degs] = this@minus - getOrElse(degs) { constantZero } - } - ) - } - /** - * Returns product of the constant represented as polynomial and the polynomial. - */ - override operator fun C.times(other: NumberedPolynomial): NumberedPolynomial = - NumberedPolynomial( - other.coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this@times * this[degs]!! - } - ) - - /** - * Returns sum of the constant represented as polynomial and the polynomial. - */ - override operator fun NumberedPolynomial.plus(other: C): NumberedPolynomial = - with(coefficients) { - if (isEmpty()) NumberedPolynomial(mapOf(emptyList() to other)) - else NumberedPolynomial( - toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = getOrElse(degs) { constantZero } + other - } - ) - } - /** - * Returns difference between the constant represented as polynomial and the polynomial. - */ - override operator fun NumberedPolynomial.minus(other: C): NumberedPolynomial = - with(coefficients) { - if (isEmpty()) NumberedPolynomial(mapOf(emptyList() to other)) - else NumberedPolynomial( - toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = getOrElse(degs) { constantZero } - other - } - ) - } - /** - * Returns product of the constant represented as polynomial and the polynomial. - */ - override operator fun NumberedPolynomial.times(other: C): NumberedPolynomial = - NumberedPolynomial( - coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this[degs]!! * other - } - ) - - /** - * Converts the constant [value] to polynomial. - */ - public override fun number(value: C): NumberedPolynomial = - NumberedPolynomial(mapOf(emptyList() to value)) - - /** - * Returns negation of the polynomial. - */ - override fun NumberedPolynomial.unaryMinus(): NumberedPolynomial = - NumberedPolynomial( - coefficients.mapValues { -it.value } - ) - /** - * Returns sum of the polynomials. - */ - override operator fun NumberedPolynomial.plus(other: NumberedPolynomial): NumberedPolynomial = - NumberedPolynomial( - buildMap(coefficients.size + other.coefficients.size) { - other.coefficients.mapValuesTo(this) { it.value } - other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value } - } - ) - /** - * Returns difference of the polynomials. - */ - override operator fun NumberedPolynomial.minus(other: NumberedPolynomial): NumberedPolynomial = - NumberedPolynomial( - buildMap(coefficients.size + other.coefficients.size) { - other.coefficients.mapValuesTo(this) { it.value } - other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value } - } - ) - /** - * Returns product of the polynomials. - */ - override operator fun NumberedPolynomial.times(other: NumberedPolynomial): NumberedPolynomial = - NumberedPolynomial( - 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 - this[degs] = if (degs in this) this[degs]!! + c else c - } - } - ) - - /** - * Instance of zero polynomial (zero of the polynomial ring). - */ - override val zero: NumberedPolynomial = NumberedPolynomial(emptyMap()) - /** - * Instance of unit polynomial (unit of the polynomial ring). - */ - override val one: NumberedPolynomial = - NumberedPolynomial( - mapOf( - emptyList() to constantOne // 1 * x_1^0 * x_2^0 * ... - ) - ) - - /** - * 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.entries.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.entries.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.entries.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.entries.maxOfOrNull { (degs, _) -> degs.getOrElse(variable) { 0u } } ?: 0u - /** - * Counts degree of the polynomial by the specified [variables]. - */ - public fun NumberedPolynomial.degreeBy(variables: Collection): UInt = - coefficients.entries.maxOfOrNull { (degs, _) -> - degs.withIndex().filter { (index, _) -> index in variables }.sumOf { it.value } - } ?: 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 } - - @Suppress("NOTHING_TO_INLINE") - public inline fun NumberedPolynomial.substitute(argument: Map): NumberedPolynomial = this.substitute(ring, argument) - @Suppress("NOTHING_TO_INLINE") - @JvmName("substitutePolynomial") - public inline fun NumberedPolynomial.substitute(argument: Map>): NumberedPolynomial = this.substitute(ring, argument) - - @Suppress("NOTHING_TO_INLINE") - public inline fun NumberedPolynomial.asFunction(): (Map) -> NumberedPolynomial = { this.substitute(ring, it) } - @Suppress("NOTHING_TO_INLINE") - public inline fun NumberedPolynomial.asFunctionOnConstants(): (Map) -> NumberedPolynomial = { this.substitute(ring, it) } - @Suppress("NOTHING_TO_INLINE") - public inline fun NumberedPolynomial.asFunctionOnPolynomials(): (Map>) -> NumberedPolynomial = { this.substitute(ring, it) } - - @Suppress("NOTHING_TO_INLINE") - public inline operator fun NumberedPolynomial.invoke(argument: Map): NumberedPolynomial = this.substitute(ring, argument) - @Suppress("NOTHING_TO_INLINE") - @JvmName("invokePolynomial") - public inline operator fun NumberedPolynomial.invoke(argument: Map>): NumberedPolynomial = this.substitute(ring, argument) - - // FIXME: Move to other constructors with context receiver - public fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(emptyList() to this)) -} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt deleted file mode 100644 index 30c7f0188..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.invoke -import kotlin.math.max - - -public class NumberedRationalFunction internal constructor( - public override val numerator: NumberedPolynomial, - public override val denominator: NumberedPolynomial -) : RationalFunction> { - override fun toString(): String = "NumberedRationalFunction${numerator.coefficients}/${denominator.coefficients}" -} - -public class NumberedRationalFunctionSpace> ( - public val ring: A, -) : - RationalFunctionalSpaceOverPolynomialSpace< - C, - NumberedPolynomial, - NumberedRationalFunction, - NumberedPolynomialSpace, - >, - PolynomialSpaceOfFractions< - C, - NumberedPolynomial, - NumberedRationalFunction, - >() { - - override val polynomialRing : NumberedPolynomialSpace = NumberedPolynomialSpace(ring) - override fun constructRationalFunction( - numerator: NumberedPolynomial, - denominator: NumberedPolynomial - ): NumberedRationalFunction = - NumberedRationalFunction(numerator, denominator) - - /** - * Instance of zero rational function (zero of the rational functions ring). - */ - public override val zero: NumberedRationalFunction = NumberedRationalFunction(polynomialZero, polynomialOne) - /** - * Instance of unit polynomial (unit of the rational functions ring). - */ - public override val one: NumberedRationalFunction = NumberedRationalFunction(polynomialOne, polynomialOne) - - /** - * 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: Разобрать - -// operator fun invoke(arg: Map): NumberedRationalFunction = -// NumberedRationalFunction( -// numerator(arg), -// denominator(arg) -// ) -// -// @JvmName("invokePolynomial") -// operator fun invoke(arg: Map>): NumberedRationalFunction = -// NumberedRationalFunction( -// numerator(arg), -// denominator(arg) -// ) -// -// @JvmName("invokeRationalFunction") -// operator fun invoke(arg: Map>): NumberedRationalFunction { -// var num = numerator invokeRFTakeNumerator arg -// var den = denominator invokeRFTakeNumerator arg -// for (variable in 0 until max(numerator.countOfVariables, denominator.countOfVariables)) if (variable in arg) { -// val degreeDif = numerator.degrees.getOrElse(variable) { 0 } - denominator.degrees.getOrElse(variable) { 0 } -// if (degreeDif > 0) -// den = multiplyByPower(den, arg[variable]!!.denominator, degreeDif) -// else -// num = multiplyByPower(num, arg[variable]!!.denominator, -degreeDif) -// } -// return NumberedRationalFunction(num, den) -// } -// -// override fun toString(): String = toString(Polynomial.variableName) -// -// fun toString(withVariableName: String = Polynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toString(withVariableName) -// else -> "${numerator.toStringWithBrackets(withVariableName)}/${denominator.toStringWithBrackets(withVariableName)}" -// } -// -// fun toString(namer: (Int) -> String): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toString(namer) -// else -> "${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)}" -// } -// -// fun toStringWithBrackets(withVariableName: String = Polynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toStringWithBrackets(withVariableName) -// else -> "(${numerator.toStringWithBrackets(withVariableName)}/${denominator.toStringWithBrackets(withVariableName)})" -// } -// -// fun toStringWithBrackets(namer: (Int) -> String): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toStringWithBrackets(namer) -// else -> "(${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)})" -// } -// -// fun toReversedString(withVariableName: String = Polynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedString(withVariableName) -// else -> "${numerator.toReversedStringWithBrackets(withVariableName)}/${denominator.toReversedStringWithBrackets(withVariableName)}" -// } -// -// fun toReversedString(namer: (Int) -> String): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedString(namer) -// else -> "${numerator.toReversedStringWithBrackets(namer)}/${denominator.toReversedStringWithBrackets(namer)}" -// } -// -// fun toReversedStringWithBrackets(withVariableName: String = Polynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedStringWithBrackets(withVariableName) -// else -> "(${numerator.toReversedStringWithBrackets(withVariableName)}/${denominator.toReversedStringWithBrackets(withVariableName)})" -// } -// -// fun toReversedStringWithBrackets(namer: (Int) -> String): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedStringWithBrackets(namer) -// else -> "(${numerator.toReversedStringWithBrackets(namer)}/${denominator.toReversedStringWithBrackets(namer)})" -// } -} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt deleted file mode 100644 index 612b00535..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.operations.Ring - -/** - * Represents piecewise-defined function. - * - * @param T the piece key type. - * @param R the sub-function type. - */ -public fun interface Piecewise { - /** - * Returns the appropriate sub-function for given piece key. - */ - public fun findPiece(arg: T): R? -} - -/** - * Represents piecewise-defined function where all the sub-functions are polynomials. - * - * @property pieces An ordered list of range-polynomial pairs. The list does not in general guarantee that there are no - * "holes" in it. - */ -public interface PiecewisePolynomial> : Piecewise> { - public val pieces: Collection, ListPolynomial>> - - override fun findPiece(arg: T): ListPolynomial? -} - -/** - * A generic piecewise without constraints on how pieces are placed - */ -@PerformancePitfall("findPiece method of resulting piecewise is slow") -public fun > PiecewisePolynomial( - pieces: Collection, ListPolynomial>>, -): PiecewisePolynomial = object : PiecewisePolynomial { - override val pieces: Collection, ListPolynomial>> = pieces - - override fun findPiece(arg: T): ListPolynomial? = pieces.firstOrNull { arg in it.first }?.second -} - -/** - * An optimized piecewise that uses not separate pieces, but a range separated by delimiters. - * The pieces search is logarithmic. - */ -private class OrderedPiecewisePolynomial>( - override val pieces: List, ListPolynomial>>, -) : PiecewisePolynomial { - - override fun findPiece(arg: T): ListPolynomial? { - val index = pieces.binarySearch { (range, _) -> - when { - arg >= range.endInclusive -> -1 - arg < range.start -> +1 - else -> 0 - } - } - return if (index < 0) null else pieces[index].second - } - -} - -/** - * A [Piecewise] builder where all the pieces are ordered by the [Comparable] type instances. - * - * @param T the comparable piece key type. - * @param delimiter the initial piecewise separator - */ -public class PiecewiseBuilder>(delimiter: T) { - private val delimiters: MutableList = arrayListOf(delimiter) - private val pieces: MutableList> = arrayListOf() - - /** - * Dynamically adds a piece to the right side (beyond maximum argument value of previous piece) - * - * @param right new rightmost position. If is less than current rightmost position, an error is thrown. - * @param piece the sub-function. - */ - public fun putRight(right: T, piece: ListPolynomial) { - require(right > delimiters.last()) { "New delimiter should be to the right of old one" } - delimiters += right - pieces += piece - } - - /** - * Dynamically adds a piece to the left side (beyond maximum argument value of previous piece) - * - * @param left the new leftmost position. If is less than current rightmost position, an error is thrown. - * @param piece the sub-function. - */ - public fun putLeft(left: T, piece: ListPolynomial) { - require(left < delimiters.first()) { "New delimiter should be to the left of old one" } - delimiters.add(0, left) - pieces.add(0, piece) - } - - public fun build(): PiecewisePolynomial = OrderedPiecewisePolynomial(delimiters.zipWithNext { l, r -> - l..r - }.zip(pieces)) -} - -/** - * A builder for [PiecewisePolynomial] - */ -public fun > PiecewisePolynomial( - startingPoint: T, - builder: PiecewiseBuilder.() -> Unit, -): PiecewisePolynomial = PiecewiseBuilder(startingPoint).apply(builder).build() - -/** - * Return a value of polynomial function with given [ring] a given [arg] or null if argument is outside piecewise - * definition. - */ -public fun , C : Ring> PiecewisePolynomial.substitute(ring: C, arg: T): T? = - findPiece(arg)?.substitute(ring, arg) - -/** - * Convert this polynomial to a function returning nullable value (null if argument is outside piecewise range). - */ -public fun , C : Ring> PiecewisePolynomial.asFunction(ring: C): (T) -> T? = { substitute(ring, it) } - -/** - * Convert this polynomial to a function using [defaultValue] for arguments outside the piecewise range. - */ -public fun , C : Ring> PiecewisePolynomial.asFunction(ring: C, defaultValue: T): (T) -> T = - { substitute(ring, it) ?: defaultValue } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt deleted file mode 100644 index e81a9388e..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.Ring - - -/** - * Returns the same degrees' description of the monomial, but without zero degrees. - */ -internal fun Map.cleanUp() = filterValues { it > 0U } - -// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(coefs, toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(coefs, toCheckInput) -@Suppress("FunctionName") -internal fun > A.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial { - if (!toCheckInput) return LabeledPolynomial(coefs) - - val fixedCoefs = LinkedHashMap, C>(coefs.size) - - for (entry in coefs) { - val key = entry.key.cleanUp() - val value = entry.value - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return LabeledPolynomial(fixedCoefs) -} - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs, toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs, toCheckInput) -@Suppress("FunctionName") -internal fun > A.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial { - if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) - - val fixedCoefs = LinkedHashMap, C>(pairs.size) - - for (entry in pairs) { - val key = entry.first.cleanUp() - val value = entry.second - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return LabeledPolynomial(fixedCoefs) -} - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs = pairs, toCheckInput = toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs = pairs, toCheckInput = toCheckInput) -@Suppress("FunctionName") -internal fun > A.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial { - if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) - - val fixedCoefs = LinkedHashMap, C>(pairs.size) - - for (entry in pairs) { - val key = entry.first.cleanUp() - val value = entry.second - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return LabeledPolynomial(fixedCoefs) -} - -@Suppress("FunctionName") -public fun > A.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledPolynomialSpace.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) - -@Suppress("FunctionName") -public fun > A.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledPolynomialSpace.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) - -@Suppress("FunctionName") -public fun > A.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledPolynomialSpace.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) - -//context(A) -//public fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to one)) -//context(LabeledPolynomialSpace) -//public fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to constantOne)) -//context(LabeledRationalFunctionSpace) -//public fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to constantOne)) - -public fun C.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to this)) - -@DslMarker -@UnstableKMathAPI -internal annotation class LabeledPolynomialConstructorDSL - -@UnstableKMathAPI -@LabeledPolynomialConstructorDSL -public class LabeledPolynomialTermSignatureBuilder { - private val signature: MutableMap = LinkedHashMap() - public fun build(): Map = signature - public infix fun Symbol.inPowerOf(deg: UInt) { - signature[this] = deg - } - @Suppress("NOTHING_TO_INLINE") - public inline infix fun Symbol.pow(deg: UInt): Unit = this inPowerOf deg - @Suppress("NOTHING_TO_INLINE") - public inline infix fun Symbol.`in`(deg: UInt): Unit = this inPowerOf deg - @Suppress("NOTHING_TO_INLINE") - public inline infix fun Symbol.of(deg: UInt): Unit = this inPowerOf deg -} - -@UnstableKMathAPI -public class LabeledPolynomialBuilder(private val zero: C, private val add: (C, C) -> C, capacity: Int = 0) { - private val coefficients: MutableMap, C> = LinkedHashMap(capacity) - public fun build(): LabeledPolynomial = LabeledPolynomial(coefficients) - public operator fun C.invoke(block: LabeledPolynomialTermSignatureBuilder.() -> Unit) { - val signature = LabeledPolynomialTermSignatureBuilder().apply(block).build() - coefficients[signature] = add(coefficients.getOrElse(signature) { zero }, this@invoke) - } - @Suppress("NOTHING_TO_INLINE") - public inline infix fun C.with(noinline block: LabeledPolynomialTermSignatureBuilder.() -> Unit): Unit = this.invoke(block) - @Suppress("NOTHING_TO_INLINE") - public inline infix fun (LabeledPolynomialTermSignatureBuilder.() -> Unit).with(coef: C): Unit = coef.invoke(this) - @Suppress("NOTHING_TO_INLINE") - public infix fun sig(block: LabeledPolynomialTermSignatureBuilder.() -> Unit): LabeledPolynomialTermSignatureBuilder.() -> Unit = block -} - -// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available - -@UnstableKMathAPI -@LabeledPolynomialConstructorDSL -@Suppress("FunctionName") -public inline fun > A.LabeledPolynomial(block: LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = LabeledPolynomialBuilder(zero, ::add).apply(block).build() -@UnstableKMathAPI -@LabeledPolynomialConstructorDSL -@Suppress("FunctionName") -public inline fun > A.LabeledPolynomial(capacity: Int, block: LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = LabeledPolynomialBuilder(zero, ::add, capacity).apply(block).build() -@UnstableKMathAPI -@LabeledPolynomialConstructorDSL -@Suppress("FunctionName") -public inline fun > LabeledPolynomialSpace.LabeledPolynomial(block: LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = LabeledPolynomialBuilder(constantZero, { left: C, right: C -> left + right}).apply(block).build() -@UnstableKMathAPI -@LabeledPolynomialConstructorDSL -@Suppress("FunctionName") -public inline fun > LabeledPolynomialSpace.LabeledPolynomial(capacity: Int, block: LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = LabeledPolynomialBuilder(constantZero, { left: C, right: C -> left + right}, capacity).apply(block).build() - -// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available - -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): LabeledRationalFunction = - LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients, toCheckInput = true), - LabeledPolynomial(denominatorCoefficients, toCheckInput = true) - ) -@Suppress("FunctionName") -public fun > A.LabeledRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): LabeledRationalFunction = - LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients, toCheckInput = true), - LabeledPolynomial(denominatorCoefficients, toCheckInput = true) - ) -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numerator: LabeledPolynomial): LabeledRationalFunction = - LabeledRationalFunction(numerator, polynomialOne) -@Suppress("FunctionName") -public fun > A.LabeledRationalFunction(numerator: LabeledPolynomial): LabeledRationalFunction = - LabeledRationalFunction(numerator, LabeledPolynomial(mapOf(emptyMap() to one), toCheckInput = false)) -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numeratorCoefficients: Map, C>): LabeledRationalFunction = - LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients, toCheckInput = true), - polynomialOne - ) -@Suppress("FunctionName") -public fun > A.LabeledRationalFunction(numeratorCoefficients: Map, C>): LabeledRationalFunction = - LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients, toCheckInput = true), - LabeledPolynomial(mapOf(emptyMap() to one), toCheckInput = false) - ) - -//context(A) -//public fun > Symbol.asLabeledRationalFunction() : LabeledRationalFunction = LabeledRationalFunction(asLabeledPolynomial()) -//context(LabeledRationalFunctionSpace) -//public fun > Symbol.asLabeledRationalFunction() : LabeledRationalFunction = LabeledRationalFunction(asLabeledPolynomial()) - -//context(A) -//public fun > C.asLabeledRationalFunction() : LabeledRationalFunction = LabeledRationalFunction(asLabeledPolynomial()) -//context(LabeledRationalFunctionSpace) -//public fun > C.asLabeledRationalFunction() : LabeledRationalFunction = LabeledRationalFunction(asLabeledPolynomial()) \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt deleted file mode 100644 index af918b9ae..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt +++ /dev/null @@ -1,495 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.Field -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.invoke -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract - - -// TODO: Docs - -/** - * Creates a [LabeledPolynomialSpace] over a received ring. - */ -public fun > A.labeledPolynomial(): LabeledPolynomialSpace = - LabeledPolynomialSpace(this) - -/** - * Creates a [LabeledPolynomialSpace]'s scope over a received ring. - */ -@OptIn(ExperimentalContracts::class) -public inline fun , R> A.labeledPolynomial(block: LabeledPolynomialSpace.() -> R): R { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return LabeledPolynomialSpace(this).block() -} - -///** -// * Represents the polynomial as a [String] with names of variables substituted with names from [names]. -// * Consider that monomials are sorted in lexicographic order. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.represent(names: Map = emptyMap()): String = -// coefficients.entries -// .sortedWith { o1, o2 -> LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } -// .asSequence() -// .map { (degs, t) -> -// if (degs.isEmpty()) "$t" -// else { -// when { -// t.isOne() -> "" -// t.isMinusOne() -> "-" -// else -> "$t " -// } + -// degs -// .toSortedMap() -// .filter { it.value > 0U } -// .map { (variable, deg) -> -// val variableName = names.getOrDefault(variable, variable.toString()) -// when (deg) { -// 1U -> variableName -// else -> "$variableName^$deg" -// } -// } -// .joinToString(separator = " ") { it } -// } -// } -// .joinToString(separator = " + ") { it } -// .ifEmpty { "0" } -// -///** -// * Represents the polynomial as a [String] naming variables by [namer]. -// * Consider that monomials are sorted in lexicographic order. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.represent(namer: (Symbol) -> String): String = -// coefficients.entries -// .sortedWith { o1, o2 -> LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } -// .asSequence() -// .map { (degs, t) -> -// if (degs.isEmpty()) "$t" -// else { -// when { -// t.isOne() -> "" -// t.isMinusOne() -> "-" -// else -> "$t " -// } + -// degs -// .toSortedMap() -// .filter { it.value > 0U } -// .map { (variable, deg) -> -// when (deg) { -// 1U -> namer(variable) -// else -> "${namer(variable)}^$deg" -// } -// } -// .joinToString(separator = " ") { it } -// } -// } -// .joinToString(separator = " + ") { it } -// .ifEmpty { "0" } -// -///** -// * Represents the polynomial as a [String] with names of variables substituted with names from [names] and with -// * brackets around the string if needed (i.e. when there are at least two addends in the representation). -// * Consider that monomials are sorted in lexicographic order. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.representWithBrackets(names: Map = emptyMap()): String = -// with(represent(names)) { if (coefficients.count() == 1) this else "($this)" } -// -///** -// * Represents the polynomial as a [String] naming variables by [namer] and with brackets around the string if needed -// * (i.e. when there are at least two addends in the representation). -// * Consider that monomials are sorted in lexicographic order. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.representWithBrackets(namer: (Symbol) -> String): String = -// with(represent(namer)) { if (coefficients.count() == 1) this else "($this)" } -// -///** -// * Represents the polynomial as a [String] with names of variables substituted with names from [names]. -// * Consider that monomials are sorted in **reversed** lexicographic order. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.representReversed(names: Map = emptyMap()): String = -// coefficients.entries -// .sortedWith { o1, o2 -> -LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } -// .asSequence() -// .map { (degs, t) -> -// if (degs.isEmpty()) "$t" -// else { -// when { -// t.isOne() -> "" -// t.isMinusOne() -> "-" -// else -> "$t " -// } + -// degs -// .toSortedMap() -// .filter { it.value > 0U } -// .map { (variable, deg) -> -// val variableName = names.getOrDefault(variable, variable.toString()) -// when (deg) { -// 1U -> variableName -// else -> "$variableName^$deg" -// } -// } -// .joinToString(separator = " ") { it } -// } -// } -// .joinToString(separator = " + ") { it } -// .ifEmpty { "0" } -// -///** -// * Represents the polynomial as a [String] naming variables by [namer]. -// * Consider that monomials are sorted in **reversed** lexicographic order. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.representReversed(namer: (Symbol) -> String): String = -// coefficients.entries -// .sortedWith { o1, o2 -> -LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } -// .asSequence() -// .map { (degs, t) -> -// if (degs.isEmpty()) "$t" -// else { -// when { -// t.isOne() -> "" -// t.isMinusOne() -> "-" -// else -> "$t " -// } + -// degs -// .toSortedMap() -// .filter { it.value > 0U } -// .map { (variable, deg) -> -// when (deg) { -// 1U -> namer(variable) -// else -> "${namer(variable)}^$deg" -// } -// } -// .joinToString(separator = " ") { it } -// } -// } -// .joinToString(separator = " + ") { it } -// .ifEmpty { "0" } -// -///** -// * Represents the polynomial as a [String] with names of variables substituted with names from [names] and with -// * brackets around the string if needed (i.e. when there are at least two addends in the representation). -// * Consider that monomials are sorted in **reversed** lexicographic order. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.representReversedWithBrackets(names: Map = emptyMap()): String = -// with(representReversed(names)) { if (coefficients.count() == 1) this else "($this)" } -// -///** -// * Represents the polynomial as a [String] naming variables by [namer] and with brackets around the string if needed -// * (i.e. when there are at least two addends in the representation). -// * Consider that monomials are sorted in **reversed** lexicographic order. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.representReversedWithBrackets(namer: (Symbol) -> String): String = -// with(representReversed(namer)) { if (coefficients.count() == 1) this else "($this)" } - -//operator fun > Polynomial.div(other: T): Polynomial = -// if (other.isZero()) throw ArithmeticException("/ by zero") -// else -// Polynomial( -// coefficients -// .mapValues { it.value / other }, -// toCheckInput = false -// ) - -//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 = degs.entries.asSequence().filter { it.key in args }.fold(c) { acc, (variable, deg) -> -// multiplyWithPower(acc, args[variable]!!, deg) -// } -// this[newDegs] = if (newDegs in this) this[newDegs]!! + newC else newC -// } -// } -// ) -//} -// -//// TODO: Replace with optimisation: the [result] may be unboxed, and all operations may be performed as soon as -//// possible on it -//@JvmName("substitutePolynomial") -//fun LabeledPolynomial.substitute(ring: Ring, arg: Map>) : LabeledPolynomial = -// ring.labeledPolynomial { -// if (coefficients.isEmpty()) return zero -// coefficients -// .asSequence() -// .map { (degs, c) -> -// degs.entries -// .asSequence() -// .filter { it.key in arg } -// .fold(LabeledPolynomial(mapOf(degs.filterKeys { it !in arg } to c))) { acc, (index, deg) -> -// multiplyWithPower(acc, arg[index]!!, deg) -// } -// } -// .reduce { acc, polynomial -> acc + polynomial } // TODO: Rewrite. Might be slow. -// } -// -//// TODO: Substitute rational function -// -//fun > LabeledPolynomial.asFunctionOver(ring: A): (Map) -> LabeledPolynomial = -// { substitute(ring, it) } -// -//fun > LabeledPolynomial.asPolynomialFunctionOver(ring: A): (Map>) -> LabeledPolynomial = -// { substitute(ring, it) } - -/** - * Returns algebraic derivative of received polynomial. - */ -@UnstableKMathAPI -public fun > LabeledPolynomial.derivativeWithRespectTo( - algebra: A, - variable: Symbol, -): LabeledPolynomial = algebra { - LabeledPolynomial( - buildMap(coefficients.size) { - 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. - */ -@UnstableKMathAPI -public fun > LabeledPolynomial.derivativeWithRespectTo( - algebra: A, - variables: Collection, -): LabeledPolynomial = algebra { - val cleanedVariables = variables.toSet() - if (cleanedVariables.isEmpty()) return this@derivativeWithRespectTo - LabeledPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - if (!degs.keys.containsAll(cleanedVariables)) return@forEach - put( - buildMap { - degs.forEach { (vari, deg) -> - when { - vari !in cleanedVariables -> put(vari, deg) - deg > 1u -> put(vari, deg - 1u) - } - } - }, - cleanedVariables.fold(c) { acc, variable -> multiplyByDoubling(acc, degs[variable]!!) } - ) - } - } - ) -} - -/** - * Returns algebraic derivative of received polynomial. - */ -@UnstableKMathAPI -public fun > LabeledPolynomial.nthDerivativeWithRespectTo( - algebra: A, - variable: Symbol, - order: UInt -): LabeledPolynomial = algebra { - if (order == 0u) return this@nthDerivativeWithRespectTo - LabeledPolynomial( - buildMap(coefficients.size) { - 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. - */ -@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.size) { - 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. - */ -@UnstableKMathAPI -public fun > LabeledPolynomial.antiderivativeWithRespectTo( - algebra: A, - variable: Symbol, -): LabeledPolynomial = algebra { - LabeledPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - val newDegs = buildMap(degs.size + 1) { - put(variable, 1u) - for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) - } - put( - newDegs, - c / multiplyByDoubling(one, newDegs[variable]!!) - ) - } - } - ) -} - -/** - * Returns algebraic antiderivative of received polynomial. - */ -@UnstableKMathAPI -public fun > LabeledPolynomial.antiderivativeWithRespectTo( - algebra: A, - variables: Collection, -): LabeledPolynomial = algebra { - val cleanedVariables = variables.toSet() - if (cleanedVariables.isEmpty()) return this@antiderivativeWithRespectTo - LabeledPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - val newDegs = buildMap(degs.size + 1) { - for (variable in cleanedVariables) put(variable, 1u) - for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) - } - put( - newDegs, - cleanedVariables.fold(c) { acc, variable -> acc / multiplyByDoubling(one, newDegs[variable]!!) } - ) - } - } - ) -} - -/** - * Returns algebraic derivative of received polynomial. - */ -@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 = buildMap(degs.size + 1) { - put(variable, order) - for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) - } - 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. - */ -@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 = buildMap(degs.size + 1) { - for ((variable, order) in filteredVariablesAndOrders) put(variable, order) - for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) - } - 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-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt deleted file mode 100644 index 583160cf4..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.operations.Ring -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract - - -/** - * Creates a [LabeledRationalFunctionSpace] over a received ring. - */ -public fun > A.labeledRationalFunction(): LabeledRationalFunctionSpace = - LabeledRationalFunctionSpace(this) - -/** - * Creates a [LabeledRationalFunctionSpace]'s scope over a received ring. - */ -public inline fun , R> A.labeledRationalFunction(block: LabeledRationalFunctionSpace.() -> R): R { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return LabeledRationalFunctionSpace(this).block() -} - -//fun > LabeledRationalFunction.reduced(): LabeledRationalFunction { -// val greatestCommonDivider = polynomialGCD(numerator, denominator) -// return LabeledRationalFunction( -// numerator / greatestCommonDivider, -// denominator / greatestCommonDivider -// ) -//} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt deleted file mode 100644 index 9498c77ca..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.operations.Ring - - -/** - * Returns a [ListPolynomial] instance with given [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 }) - -/** - * Returns a [ListPolynomial] instance with given [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() }) - -public fun C.asListPolynomial() : ListPolynomial = ListPolynomial(listOf(this)) - - -// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available - -@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 } ) - ) -@Suppress("FunctionName") -public fun > ListRationalFunctionSpace.ListRationalFunction(numerator: ListPolynomial): ListRationalFunction = - ListRationalFunction(numerator, polynomialOne) -@Suppress("FunctionName") -public fun > A.ListRationalFunction(numerator: ListPolynomial): ListRationalFunction = - ListRationalFunction(numerator, ListPolynomial(listOf(one))) -@Suppress("FunctionName") -public fun > ListRationalFunctionSpace.ListRationalFunction(numeratorCoefficients: List, reverse: Boolean = false): ListRationalFunction = - ListRationalFunction( - ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), - polynomialOne - ) -@Suppress("FunctionName") -public fun > A.ListRationalFunction(numeratorCoefficients: List, reverse: Boolean = false): ListRationalFunction = - ListRationalFunction( - ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), - ListPolynomial(listOf(one)) - ) - -//context(A) -//public fun > C.asListRationalFunction() : ListRationalFunction = ListRationalFunction(asListPolynomial()) -//context(ListRationalFunctionSpace) -//public fun > C.asListRationalFunction() : ListRationalFunction = ListRationalFunction(asListPolynomial()) \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt deleted file mode 100644 index 50313cab9..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.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.min -import kotlin.math.pow - - -/** - * Removes zeros on the end of the coefficient list of polynomial. - */ -//context(PolynomialSpace) -//fun > Polynomial.removeZeros() : Polynomial = -// if (degree > -1) Polynomial(coefficients.subList(0, degree + 1)) else zero - -/** - * Creates a [ListPolynomialSpace] over a received ring. - */ -public fun > A.listPolynomial(): ListPolynomialSpace = - ListPolynomialSpace(this) - -/** - * Creates a [ListPolynomialSpace]'s scope over a received ring. - */ -public inline fun , R> A.listPolynomial(block: ListPolynomialSpace.() -> R): R { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return ListPolynomialSpace(this).block() -} - -/** - * Creates a [ScalableListPolynomialSpace] over a received scalable ring. - */ -public fun A.scalableListPolynomial(): ScalableListPolynomialSpace where A : Ring, A : ScaleOperations = - ScalableListPolynomialSpace(this) - -/** - * Creates a [ScalableListPolynomialSpace]'s scope over a received scalable ring. - */ -public inline fun A.scalableListPolynomial(block: ScalableListPolynomialSpace.() -> R): R where A : Ring, A : ScaleOperations { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return ScalableListPolynomialSpace(this).block() -} - -@Suppress("NOTHING_TO_INLINE") -internal inline fun copyTo( - origin: List, - originDegree: Int, - target: MutableList, -) { - for (deg in 0 .. originDegree) target[deg] = origin[deg] -} - -@Suppress("NOTHING_TO_INLINE") -internal inline fun multiplyAddingToUpdater( - ring: Ring, - multiplicand: MutableList, - multiplicandDegree: Int, - multiplier: List, - multiplierDegree: Int, - updater: MutableList, - zero: C, -) { - multiplyAddingTo( - ring = ring, - multiplicand = multiplicand, - multiplicandDegree = multiplicandDegree, - multiplier = multiplier, - multiplierDegree = multiplierDegree, - target = updater - ) - for (updateDeg in 0 .. multiplicandDegree + multiplierDegree) { - multiplicand[updateDeg] = updater[updateDeg] - updater[updateDeg] = zero - } -} - -@Suppress("NOTHING_TO_INLINE") -internal inline fun multiplyAddingTo( - ring: Ring, - multiplicand: List, - multiplicandDegree: Int, - multiplier: List, - multiplierDegree: Int, - target: MutableList -) = ring { - for (d in 0 .. multiplicandDegree + multiplierDegree) - for (k in max(0, d - multiplierDegree)..min(multiplicandDegree, d)) - target[d] += multiplicand[k] * multiplier[d - k] -} - -/** - * Evaluates the value of the given double polynomial for given double argument. - */ -public fun ListPolynomial.substitute(arg: Double): Double = - coefficients.reduceIndexedOrNull { index, acc, c -> - acc + c * arg.pow(index) - } ?: .0 - -/** - * Evaluates the value of the given polynomial for given 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@ring zero - var result: C = coefficients.last() - for (j in coefficients.size - 2 downTo 0) { - result = (arg * result) + coefficients[j] - } - return result -} - -public fun ListPolynomial.substitute(ring: Ring, arg: ListPolynomial) : ListPolynomial = ring { - if (coefficients.isEmpty()) return ListPolynomial(emptyList()) - - val thisDegree = coefficients.lastIndex - if (thisDegree == -1) return ListPolynomial(emptyList()) - val argDegree = arg.coefficients.lastIndex - if (argDegree == -1) return coefficients[0].asListPolynomial() - val constantZero = zero - val resultCoefs: MutableList = MutableList(thisDegree * argDegree + 1) { constantZero } - resultCoefs[0] = coefficients[thisDegree] - val resultCoefsUpdate: MutableList = MutableList(thisDegree * argDegree + 1) { constantZero } - var resultDegree = 0 - for (deg in thisDegree - 1 downTo 0) { - resultCoefsUpdate[0] = coefficients[deg] - multiplyAddingToUpdater( - ring = ring, - multiplicand = resultCoefs, - multiplicandDegree = resultDegree, - multiplier = arg.coefficients, - multiplierDegree = argDegree, - updater = resultCoefsUpdate, - zero = constantZero - ) - resultDegree += argDegree - } - - return ListPolynomial(resultCoefs) -} - -/** - * Represent the polynomial as a regular context-less function. - */ -public fun > ListPolynomial.asFunction(ring: A): (C) -> C = { substitute(ring, it) } - -/** - * Represent the polynomial as a regular context-less function. - */ -public fun > ListPolynomial.asPolynomialFunctionOver(ring: A): (ListPolynomial) -> ListPolynomial = { substitute(ring, it) } - -/** - * Returns algebraic derivative of received polynomial. - */ -@UnstableKMathAPI -public fun ListPolynomial.derivative( - algebra: A, -): ListPolynomial where A : Ring, A : NumericAlgebra = algebra { - ListPolynomial( - buildList(max(0, coefficients.size - 1)) { - for (deg in 1 .. coefficients.lastIndex) add(number(deg) * coefficients[deg]) - } - ) -} - -/** - * Returns algebraic derivative of received polynomial. - */ -@UnstableKMathAPI -public fun ListPolynomial.nthDerivative( - algebra: A, - order: Int, -): ListPolynomial where A : Ring, A : NumericAlgebra = algebra { - 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( - algebra: A, -): ListPolynomial where A : Field, A : NumericAlgebra = algebra { - ListPolynomial( - buildList(coefficients.size + 1) { - add(zero) - coefficients.mapIndexedTo(this) { index, t -> t / number(index + 1) } - } - ) -} - -/** - * Returns algebraic antiderivative of received polynomial. - */ -@UnstableKMathAPI -public fun ListPolynomial.nthAntiderivative( - algebra: A, - order: Int, -): ListPolynomial where A : Field, A : NumericAlgebra = algebra { - 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) } } - } - ) -} - -/** - * Compute a definite integral of a given polynomial in a [range] - */ -@UnstableKMathAPI -public fun > ListPolynomial.integrate( - algebra: Field, - range: ClosedRange, -): C = algebra { - val integral = antiderivative(algebra) - integral.substitute(algebra, range.endInclusive) - integral.substitute(algebra, range.start) -} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listRationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listRationalFunctionUtil.kt deleted file mode 100644 index 367212588..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listRationalFunctionUtil.kt +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.operations.Field -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.invoke -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract -import kotlin.math.max - - -/** - * Creates a [ListRationalFunctionSpace] over a received ring. - */ -public fun > A.listRationalFunction(): ListRationalFunctionSpace = - ListRationalFunctionSpace(this) - -/** - * Creates a [ListRationalFunctionSpace]'s scope over a received ring. - */ -public inline fun , R> A.listRationalFunction(block: ListRationalFunctionSpace.() -> R): R { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return ListRationalFunctionSpace(this).block() -} - -/** - * Evaluates the value of the given double polynomial for given double argument. - */ -public fun ListRationalFunction.substitute(arg: Double): Double = - numerator.substitute(arg) / denominator.substitute(arg) - -/** - * Evaluates the value of the given polynomial for given 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) -} - -/** - * Returns numerator (polynomial) of rational function gotten by substitution rational function [arg] to the polynomial instance. - * More concrete, if [arg] is a fraction `f(x)/g(x)` and the receiving instance is `p(x)`, then - * ``` - * p(f/g) * g^deg(p) - * ``` - * is returned. - * - * Used in [ListPolynomial.substitute] and [ListRationalFunction.substitute] for performance optimisation. - */ // TODO: Дописать -internal fun ListPolynomial.substituteRationalFunctionTakeNumerator(ring: Ring, arg: ListRationalFunction): ListPolynomial = ring { - if (coefficients.isEmpty()) return ListPolynomial(emptyList()) - - val thisDegree = coefficients.lastIndex - if (thisDegree == -1) return ListPolynomial(emptyList()) - val thisDegreeLog2 = 31 - thisDegree.countLeadingZeroBits() - val numeratorDegree = arg.numerator.coefficients.lastIndex - val denominatorDegree = arg.denominator.coefficients.lastIndex - val argDegree = max(numeratorDegree, denominatorDegree) - val constantZero = zero - val powersOf2 = buildList(thisDegreeLog2 + 1) { - var result = 1 - for (exp in 0 .. thisDegreeLog2) { - add(result) - result = result shl 1 - } - } - val hashes = powersOf2.runningReduce { acc, i -> acc + i } - val numeratorPowers = buildList>(thisDegreeLog2 + 1) { - add(arg.numerator.coefficients) - repeat(thisDegreeLog2) { - val next = MutableList(powersOf2[it + 1] * numeratorDegree + 1) { constantZero } - add(next) - val last = last() - multiplyAddingTo( - ring = ring, - multiplicand = last, - multiplicandDegree = powersOf2[it] * numeratorDegree + 1, - multiplier = last, - multiplierDegree = powersOf2[it] * numeratorDegree + 1, - target = next, - ) - } - } - val denominatorPowers = buildList>(thisDegreeLog2 + 1) { - add(arg.denominator.coefficients) - repeat(thisDegreeLog2) { - val next = MutableList(powersOf2[it + 1] * denominatorDegree + 1) { constantZero } - add(next) - val last = last() - multiplyAddingTo( - ring = ring, - multiplicand = last, - multiplicandDegree = powersOf2[it] * denominatorDegree + 1, - multiplier = last, - multiplierDegree = powersOf2[it] * denominatorDegree + 1, - target = next, - ) - } - } - val levelResultCoefsPool = buildList>(thisDegreeLog2 + 1) { - repeat(thisDegreeLog2 + 1) { - add(MutableList(hashes[it] * argDegree) { constantZero }) - } - } - val edgedMultiplier = MutableList(0) { TODO() } - val edgedMultiplierUpdater = MutableList(0) { TODO() } - - fun MutableList.reset() { - for (i in indices) set(i, constantZero) - } - - fun processLevel(level: Int, start: Int, end: Int) : List { - val levelResultCoefs = levelResultCoefsPool[level + 1] - - if (level == -1) { - levelResultCoefs[0] = coefficients[start] - } else { - levelResultCoefs.reset() - multiplyAddingTo( - ring = ring, - multiplicand = processLevel(level = level - 1, start = start, end = (start + end) / 2), - multiplicandDegree = hashes[level] * argDegree, - multiplier = denominatorPowers[level], - multiplierDegree = powersOf2[level] * denominatorDegree, - target = levelResultCoefs - ) - multiplyAddingTo( - ring = ring, - multiplicand = processLevel(level = level - 1, start = (start + end) / 2, end = end), - multiplicandDegree = hashes[level] * argDegree, - multiplier = numeratorPowers[level], - multiplierDegree = powersOf2[level] * numeratorDegree, - target = levelResultCoefs - ) - } - - return levelResultCoefs - } - - fun processLevelEdged(level: Int, start: Int, end: Int) : List { - val levelResultCoefs = levelResultCoefsPool[level + 1] - - if (level == -1) { - levelResultCoefs[0] = coefficients[start] - } else { - val levelsPowerOf2 = powersOf2[level] - if (end - start >= levelsPowerOf2) { - multiplyAddingTo( - ring = ring, - multiplicand = processLevelEdged(level = level - 1, start = start + levelsPowerOf2, end = end), - multiplicandDegree = hashes[level] * argDegree, // TODO: Ввести переменную - multiplier = numeratorPowers[level], - multiplierDegree = powersOf2[level] * numeratorDegree, - target = levelResultCoefs - ) - multiplyAddingTo( - ring = ring, - multiplicand = processLevel(level = level - 1, start = start, end = start + levelsPowerOf2), - multiplicandDegree = hashes[level] * argDegree, - multiplier = edgedMultiplier, - multiplierDegree = max((hashes[level] and thisDegree) - powersOf2[level] + 1, 0) * denominatorDegree, // TODO: Ввести переменную - target = levelResultCoefs - ) - if (level != thisDegreeLog2) { - multiplyAddingToUpdater( - ring = ring, - multiplicand = edgedMultiplier, - multiplicandDegree = max((hashes[level] and thisDegree) - powersOf2[level] + 1, 0) * denominatorDegree, // TODO: Ввести переменную - multiplier = denominatorPowers[level], - multiplierDegree = powersOf2[level] * denominatorDegree, - updater = edgedMultiplierUpdater, - zero = constantZero - ) - } - } else { - copyTo( - origin = processLevelEdged(level = level - 1, start = start + levelsPowerOf2, end = end), - originDegree = hashes[level] * argDegree, // TODO: Ввести переменную - target = levelResultCoefs - ) - } - } - - return levelResultCoefs - } - - return ListPolynomial( - processLevelEdged( - level = thisDegreeLog2, - start = 0, - end = thisDegree + 1 - ) - ) -} - -//operator fun > RationalFunction.invoke(arg: T): T = numerator(arg) / denominator(arg) -// -//fun > RationalFunction.reduced(): RationalFunction = -// polynomialGCD(numerator, denominator).let { -// RationalFunction( -// numerator / it, -// denominator / it -// ) -// } - -///** -// * Returns result of applying formal derivative to the polynomial. -// * -// * @param T Field where we are working now. -// * @return Result of the operator. -// */ -//fun > RationalFunction.derivative() = -// RationalFunction( -// numerator.derivative() * denominator - denominator.derivative() * numerator, -// denominator * denominator -// ) \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt deleted file mode 100644 index dca8a0cff..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.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) - -// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(coefs, toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(coefs, toCheckInput) -@Suppress("FunctionName") -internal fun > A.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial { - if (!toCheckInput) return NumberedPolynomial(coefs) - - val fixedCoefs = mutableMapOf, C>() - - for (entry in coefs) { - val key = entry.key.cleanUp() - val value = entry.value - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return NumberedPolynomial(fixedCoefs) -} - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs, toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs, toCheckInput) -@Suppress("FunctionName") -internal fun > A.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial { - if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) - - val fixedCoefs = mutableMapOf, C>() - - for (entry in pairs) { - val key = entry.first.cleanUp() - val value = entry.second - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return NumberedPolynomial(fixedCoefs) -} - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs = pairs, toCheckInput = toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs = pairs, toCheckInput = toCheckInput) -@Suppress("FunctionName") -internal fun > A.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial { - if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) - - val fixedCoefs = mutableMapOf, C>() - - for (entry in pairs) { - val key = entry.first.cleanUp() - val value = entry.second - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return NumberedPolynomial(fixedCoefs) -} - -@Suppress("FunctionName") -public fun > A.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedPolynomialSpace.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) - -@Suppress("FunctionName") -public fun > A.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedPolynomialSpace.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) - -@Suppress("FunctionName") -public fun > A.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedPolynomialSpace.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) - -public fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(emptyList() to this)) - -@DslMarker -@UnstableKMathAPI -internal annotation class NumberedPolynomialConstructorDSL - -@UnstableKMathAPI -@NumberedPolynomialConstructorDSL -public class NumberedPolynomialTermSignatureBuilder { - private val signature: MutableList = ArrayList() - public fun build(): List = signature - public infix fun Int.inPowerOf(deg: UInt) { - if (this > signature.lastIndex) { - signature.addAll(List(this - signature.lastIndex - 1) { 0u }) - signature.add(deg) - } else { - signature[this] = deg - } - } - @Suppress("NOTHING_TO_INLINE") - public inline infix fun Int.pow(deg: UInt): Unit = this inPowerOf deg - @Suppress("NOTHING_TO_INLINE") - public inline infix fun Int.`in`(deg: UInt): Unit = this inPowerOf deg - @Suppress("NOTHING_TO_INLINE") - public inline infix fun Int.of(deg: UInt): Unit = this inPowerOf deg -} - -@UnstableKMathAPI -public class NumberedPolynomialBuilder(private val zero: C, private val add: (C, C) -> C, capacity: Int = 0) { - private val coefficients: MutableMap, C> = LinkedHashMap(capacity) - public fun build(): NumberedPolynomial = NumberedPolynomial(coefficients) - public operator fun C.invoke(block: NumberedPolynomialTermSignatureBuilder.() -> Unit) { - val signature = NumberedPolynomialTermSignatureBuilder().apply(block).build() - coefficients[signature] = add(coefficients.getOrElse(signature) { zero }, this@invoke) - } - @Suppress("NOTHING_TO_INLINE") - public inline infix fun C.with(noinline block: NumberedPolynomialTermSignatureBuilder.() -> Unit): Unit = this.invoke(block) - @Suppress("NOTHING_TO_INLINE") - public inline infix fun (NumberedPolynomialTermSignatureBuilder.() -> Unit).with(coef: C): Unit = coef.invoke(this) - @Suppress("NOTHING_TO_INLINE") - public infix fun sig(block: NumberedPolynomialTermSignatureBuilder.() -> Unit): NumberedPolynomialTermSignatureBuilder.() -> Unit = block -} - -// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available - -@UnstableKMathAPI -@NumberedPolynomialConstructorDSL -@Suppress("FunctionName") -public inline fun > A.NumberedPolynomial(block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder(zero, ::add).apply(block).build() -@UnstableKMathAPI -@NumberedPolynomialConstructorDSL -@Suppress("FunctionName") -public inline fun > A.NumberedPolynomial(capacity: Int, block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder(zero, ::add, capacity).apply(block).build() -@UnstableKMathAPI -@NumberedPolynomialConstructorDSL -@Suppress("FunctionName") -public inline fun > NumberedPolynomialSpace.NumberedPolynomial(block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder(constantZero, { left: C, right: C -> left + right}).apply(block).build() -@UnstableKMathAPI -@NumberedPolynomialConstructorDSL -@Suppress("FunctionName") -public inline fun > NumberedPolynomialSpace.NumberedPolynomial(capacity: Int, block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder(constantZero, { left: C, right: C -> left + right}, capacity).apply(block).build() - -// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available - -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): NumberedRationalFunction = - NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients, toCheckInput = true), - NumberedPolynomial(denominatorCoefficients, toCheckInput = true) - ) -@Suppress("FunctionName") -public fun > A.NumberedRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): NumberedRationalFunction = - NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients, toCheckInput = true), - NumberedPolynomial(denominatorCoefficients, toCheckInput = true) - ) -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numerator: NumberedPolynomial): NumberedRationalFunction = - NumberedRationalFunction(numerator, polynomialOne) -@Suppress("FunctionName") -public fun > A.NumberedRationalFunction(numerator: NumberedPolynomial): NumberedRationalFunction = - NumberedRationalFunction(numerator, NumberedPolynomial(mapOf(emptyList() to one), toCheckInput = false)) -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numeratorCoefficients: Map, C>): NumberedRationalFunction = - NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients, toCheckInput = true), - polynomialOne - ) -@Suppress("FunctionName") -public fun > A.NumberedRationalFunction(numeratorCoefficients: Map, C>): NumberedRationalFunction = - NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients, toCheckInput = true), - NumberedPolynomial(mapOf(emptyList() to one), toCheckInput = false) - ) - -//context(A) -//public fun > C.asNumberedRationalFunction() : NumberedRationalFunction = NumberedRationalFunction(asLabeledPolynomial()) -//context(NumberedRationalFunctionSpace) -//public fun > C.asNumberedRationalFunction() : NumberedRationalFunction = NumberedRationalFunction(asLabeledPolynomial()) \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt deleted file mode 100644 index ad817c7ba..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt +++ /dev/null @@ -1,528 +0,0 @@ -package space.kscience.kmath.functions - -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.* -import kotlin.contracts.* -import kotlin.jvm.JvmName -import kotlin.math.max - - -// TODO: Docs - -/** - * Creates a [NumberedPolynomialSpace] over a received ring. - */ -public fun > A.numberedPolynomial(): NumberedPolynomialSpace = - NumberedPolynomialSpace(this) - -/** - * Creates a [NumberedPolynomialSpace]'s scope over a received ring. - */ -@OptIn(ExperimentalContracts::class) -public inline fun , R> A.numberedPolynomial(block: NumberedPolynomialSpace.() -> R): R { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return NumberedPolynomialSpace(this).block() -} - -///** -// * Represents the polynomial as a [String] where name of variable with index `i` is [withVariableName] + `"_${i+1}"`. -// * Consider that monomials are sorted in lexicographic order. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial.represent(withVariableName: String = NumberedPolynomial.defaultVariableName): String = -// coefficients.entries -// .sortedWith { o1, o2 -> NumberedPolynomial.monomialComparator.compare(o1.key, o2.key) } -// .asSequence() -// .map { (degs, t) -> -// if (degs.isEmpty()) "$t" -// else { -// when { -// t.isOne() -> "" -// t.isMinusOne() -> "-" -// else -> "$t " -// } + -// degs -// .mapIndexed { index, deg -> -// when (deg) { -// 0U -> "" -// 1U -> "${withVariableName}_${index+1}" -// else -> "${withVariableName}_${index+1}^$deg" -// } -// } -// .filter { it.isNotEmpty() } -// .joinToString(separator = " ") { it } -// } -// } -// .joinToString(separator = " + ") { it } -// .ifEmpty { "0" } -// -///** -// * Represents the polynomial as a [String] naming variables by [namer]. -// * Consider that monomials are sorted in lexicographic order. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial.represent(namer: (Int) -> String): String = -// coefficients.entries -// .sortedWith { o1, o2 -> NumberedPolynomial.monomialComparator.compare(o1.key, o2.key) } -// .asSequence() -// .map { (degs, t) -> -// if (degs.isEmpty()) "$t" -// else { -// when { -// t.isOne() -> "" -// t.isMinusOne() -> "-" -// else -> "$t " -// } + -// degs -// .mapIndexed { index, deg -> -// when (deg) { -// 0U -> "" -// 1U -> namer(index) -// else -> "${namer(index)}^$deg" -// } -// } -// .filter { it.isNotEmpty() } -// .joinToString(separator = " ") { it } -// } -// } -// .joinToString(separator = " + ") { it } -// .ifEmpty { "0" } -// -///** -// * Represents the polynomial as a [String] where name of variable with index `i` is [withVariableName] + `"_${i+1}"` -// * and with brackets around the string if needed (i.e. when there are at least two addends in the representation). -// * Consider that monomials are sorted in lexicographic order. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial.representWithBrackets(withVariableName: String = NumberedPolynomial.defaultVariableName): String = -// with(represent(withVariableName)) { if (coefficients.count() == 1) this else "($this)" } -// -///** -// * Represents the polynomial as a [String] naming variables by [namer] and with brackets around the string if needed -// * (i.e. when there are at least two addends in the representation). -// * Consider that monomials are sorted in lexicographic order. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial.representWithBrackets(namer: (Int) -> String): String = -// with(represent(namer)) { if (coefficients.count() == 1) this else "($this)" } -// -///** -// * Represents the polynomial as a [String] where name of variable with index `i` is [withVariableName] + `"_${i+1}"`. -// * Consider that monomials are sorted in **reversed** lexicographic order. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial.representReversed(withVariableName: String = NumberedPolynomial.defaultVariableName): String = -// coefficients.entries -// .sortedWith { o1, o2 -> -NumberedPolynomial.monomialComparator.compare(o1.key, o2.key) } -// .asSequence() -// .map { (degs, t) -> -// if (degs.isEmpty()) "$t" -// else { -// when { -// t.isOne() -> "" -// t.isMinusOne() -> "-" -// else -> "$t " -// } + -// degs -// .mapIndexed { index, deg -> -// when (deg) { -// 0U -> "" -// 1U -> "${withVariableName}_${index+1}" -// else -> "${withVariableName}_${index+1}^$deg" -// } -// } -// .filter { it.isNotEmpty() } -// .joinToString(separator = " ") { it } -// } -// } -// .joinToString(separator = " + ") { it } -// .ifEmpty { "0" } -// -///** -// * Represents the polynomial as a [String] naming variables by [namer]. -// * Consider that monomials are sorted in **reversed** lexicographic order. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial.representReversed(namer: (Int) -> String): String = -// coefficients.entries -// .sortedWith { o1, o2 -> -NumberedPolynomial.monomialComparator.compare(o1.key, o2.key) } -// .asSequence() -// .map { (degs, t) -> -// if (degs.isEmpty()) "$t" -// else { -// when { -// t.isOne() -> "" -// t.isMinusOne() -> "-" -// else -> "$t " -// } + -// degs -// .mapIndexed { index, deg -> -// when (deg) { -// 0U -> "" -// 1U -> namer(index) -// else -> "${namer(index)}^$deg" -// } -// } -// .filter { it.isNotEmpty() } -// .joinToString(separator = " ") { it } -// } -// } -// .joinToString(separator = " + ") { it } -// .ifEmpty { "0" } -// -///** -// * Represents the polynomial as a [String] where name of variable with index `i` is [withVariableName] + `"_${i+1}"` -// * and with brackets around the string if needed (i.e. when there are at least two addends in the representation). -// * Consider that monomials are sorted in **reversed** lexicographic order. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial.representReversedWithBrackets(withVariableName: String = NumberedPolynomial.defaultVariableName): String = -// with(representReversed(withVariableName)) { if (coefficients.count() == 1) this else "($this)" } -// -///** -// * Represents the polynomial as a [String] naming variables by [namer] and with brackets around the string if needed -// * (i.e. when there are at least two addends in the representation). -// * Consider that monomials are sorted in **reversed** lexicographic order. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial.representReversedWithBrackets(namer: (Int) -> String): String = -// with(representReversed(namer)) { if (coefficients.count() == 1) this else "($this)" } - -//public fun NumberedPolynomial.substitute(ring: Ring, args: Map): NumberedPolynomial = ring { -// if (coefficients.isEmpty()) return this@substitute -// NumberedPolynomial( -// buildMap { -// coefficients.forEach { (degs, c) -> -// val newDegs = degs.mapIndexed { index, deg -> if (index in args) 0U else deg }.cleanUp() -// val newC = degs.foldIndexed(c) { index, acc, deg -> -// if (index in args) multiplyWithPower(acc, args[index]!!, deg) -// else acc -// } -// this[newDegs] = if (newDegs in this) this[newDegs]!! + newC else newC -// } -// } -// ) -//} -// -//// TODO: Replace with optimisation: the [result] may be unboxed, and all operations may be performed as soon as -//// possible on it -//@JvmName("substitutePolynomial") -//public fun NumberedPolynomial.substitute(ring: Ring, arg: Map>) : NumberedPolynomial = -// ring.numberedPolynomialSpace { -// if (coefficients.isEmpty()) return zero -// coefficients -// .asSequence() -// .map { (degs, c) -> -// degs.foldIndexed( -// NumberedPolynomial( -// degs.mapIndexed { index, deg -> if (index in arg) 0U else deg } to c -// ) -// ) { index, acc, deg -> if (index in arg) multiplyWithPower(acc, arg[index]!!, deg) else acc } -// } -// .reduce { acc, polynomial -> acc + polynomial } // TODO: Rewrite. Might be slow. -// } -// -//// TODO: Substitute rational function -// -//public fun > NumberedPolynomial.asFunctionOver(ring: A): (Map) -> NumberedPolynomial = -// { substitute(ring, it) } -// -//public fun > NumberedPolynomial.asPolynomialFunctionOver(ring: A): (Map>) -> NumberedPolynomial = -// { substitute(ring, it) } - -//operator fun > Polynomial.div(other: T): Polynomial = -// if (other.isZero()) throw ArithmeticException("/ by zero") -// else -// Polynomial( -// coefficients -// .mapValues { it.value / other }, -// toCheckInput = false -// ) - -/** - * Evaluates the value of the given double polynomial for given double argument. - */ -public fun NumberedPolynomial.substitute(args: Map): NumberedPolynomial = Double.algebra { - val acc = LinkedHashMap, Double>(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()) - } - if (newDegs !in acc) acc[newDegs] = newC - else acc[newDegs] = acc[newDegs]!! + newC - } - return NumberedPolynomial(acc) -} - -/** - * Evaluates the value of the given polynomial for given argument. - * - * It is an implementation of [Horner's method](https://en.wikipedia.org/wiki/Horner%27s_method). - */ -public fun NumberedPolynomial.substitute(ring: Ring, args: Map): NumberedPolynomial = ring { - val acc = LinkedHashMap, C>(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) - } - if (newDegs !in acc) acc[newDegs] = newC - else acc[newDegs] = acc[newDegs]!! + newC - } - return NumberedPolynomial(acc) -} - -// TODO: (Waiting for hero) Replace with optimisation: the [result] may be unboxed, and all operations may be performed -// as soon as possible on it -@JvmName("substitutePolynomial") -public fun NumberedPolynomial.substitute(ring: Ring, args: Map>) : NumberedPolynomial = TODO() /*ring.numberedPolynomial { - val acc = LinkedHashMap, NumberedPolynomial>(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.asNumberedPolynomial()) { product, (variable, substitution) -> - val deg = degs.getOrElse(variable) { 0u } - if (deg == 0u) product else product * power(substitution, deg) - } - if (newDegs !in acc) acc[newDegs] = c.asNumberedPolynomial() - else acc[newDegs] = acc[newDegs]!! + c - } -}*/ - -/** - * Represent the polynomial as a regular context-less function. - */ -public fun > NumberedPolynomial.asFunction(ring: A): (Map) -> NumberedPolynomial = { substitute(ring, it) } - -/** - * Represent the polynomial as a regular context-less function. - */ -public fun > NumberedPolynomial.asPolynomialFunctionOver(ring: A): (Map>) -> NumberedPolynomial = { substitute(ring, it) } - -/** - * Returns algebraic derivative of received polynomial. - */ -@UnstableKMathAPI -public fun > NumberedPolynomial.derivativeWithRespectTo( - algebra: A, - variable: Int, -): NumberedPolynomial = algebra { - NumberedPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - if (degs.size > 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. - */ -@UnstableKMathAPI -public fun > NumberedPolynomial.derivativeWithRespectTo( - algebra: A, - variables: Collection, -): NumberedPolynomial = algebra { - val cleanedVariables = variables.toSet() - if (cleanedVariables.isEmpty()) return this@derivativeWithRespectTo - val maxRespectedVariable = cleanedVariables.maxOrNull()!! - NumberedPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - if (degs.size > maxRespectedVariable) return@forEach - put( - degs.mapIndexed { index, deg -> - when { - index !in cleanedVariables -> deg - deg > 0u -> deg - 1u - else -> return@forEach - } - }.cleanUp(), - cleanedVariables.fold(c) { acc, variable -> multiplyByDoubling(acc, degs[variable]) } - ) - } - } - ) -} - -/** - * Returns algebraic derivative of received polynomial. - */ -@UnstableKMathAPI -public fun > NumberedPolynomial.nthDerivativeWithRespectTo( - algebra: A, - variable: Int, - order: UInt -): NumberedPolynomial = algebra { - if (order == 0u) return this@nthDerivativeWithRespectTo - NumberedPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - if (degs.size > 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. - */ -@UnstableKMathAPI -public fun > NumberedPolynomial.nthDerivativeWithRespectTo( - algebra: A, - variablesAndOrders: Map, -): NumberedPolynomial = algebra { - 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.size > 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. - */ -@UnstableKMathAPI -public fun > NumberedPolynomial.antiderivativeWithRespectTo( - algebra: A, - variable: Int, -): NumberedPolynomial = algebra { - NumberedPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - put( - List(max(variable + 1, degs.size)) { if (it != variable) degs[it] else degs[it] + 1u }, - c / multiplyByDoubling(one, degs[variable]) - ) - } - } - ) -} - -/** - * Returns algebraic antiderivative of received polynomial. - */ -@UnstableKMathAPI -public fun > NumberedPolynomial.antiderivativeWithRespectTo( - algebra: A, - variables: Collection, -): NumberedPolynomial = algebra { - val cleanedVariables = variables.toSet() - if (cleanedVariables.isEmpty()) return this@antiderivativeWithRespectTo - val maxRespectedVariable = cleanedVariables.maxOrNull()!! - NumberedPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - put( - List(max(maxRespectedVariable + 1, degs.size)) { if (it !in variables) degs[it] else degs[it] + 1u }, - cleanedVariables.fold(c) { acc, variable -> acc / multiplyByDoubling(one, degs[variable]) } - ) - } - } - ) -} - -/** - * Returns algebraic derivative of received polynomial. - */ -@UnstableKMathAPI -public fun > NumberedPolynomial.nthAntiderivativeWithRespectTo( - algebra: A, - variable: Int, - order: UInt -): NumberedPolynomial = algebra { - if (order == 0u) return this@nthAntiderivativeWithRespectTo - NumberedPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - put( - List(max(variable + 1, degs.size)) { if (it != variable) degs[it] else degs[it] + order }, - degs[variable].let { deg -> - (deg downTo deg - order + 1u) - .fold(c) { acc, ord -> acc / multiplyByDoubling(one, ord) } - } - ) - } - } - ) -} - -/** - * Returns algebraic derivative of received polynomial. - */ -@UnstableKMathAPI -public fun > NumberedPolynomial.nthAntiderivativeWithRespectTo( - algebra: A, - variablesAndOrders: Map, -): NumberedPolynomial = algebra { - 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[it] + filteredVariablesAndOrders.getOrElse(it) { 0u } }, - filteredVariablesAndOrders.entries.fold(c) { acc1, (index, order) -> - degs[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-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt deleted file mode 100644 index 5cd0679ab..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.operations.Ring -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract - - -/** - * Creates a [NumberedRationalFunctionSpace] over a received ring. - */ -public fun > A.numberedRationalFunction(): NumberedRationalFunctionSpace = - NumberedRationalFunctionSpace(this) - -/** - * Creates a [NumberedRationalFunctionSpace]'s scope over a received ring. - */ -public inline fun , R> A.numberedRationalFunction(block: NumberedRationalFunctionSpace.() -> R): R { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return NumberedRationalFunctionSpace(this).block() -} - -//fun > NumberedRationalFunction.reduced(): NumberedRationalFunction { -// val greatestCommonDivider = polynomialGCD(numerator, denominator) -// return NumberedRationalFunction( -// numerator / greatestCommonDivider, -// denominator / greatestCommonDivider -// ) -//} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt deleted file mode 100644 index 0fcd4c6e5..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.integration - -import space.kscience.kmath.functions.PiecewisePolynomial -import space.kscience.kmath.functions.integrate -import space.kscience.kmath.functions.antiderivative -import space.kscience.kmath.interpolation.PolynomialInterpolator -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.structures.Buffer -import space.kscience.kmath.structures.DoubleBuffer -import space.kscience.kmath.structures.MutableBufferFactory - -/** - * Compute analytical indefinite integral of this [PiecewisePolynomial], keeping all intervals intact - */ -@OptIn(PerformancePitfall::class) -@UnstableKMathAPI -public fun > PiecewisePolynomial.integrate(algebra: Field): PiecewisePolynomial = - PiecewisePolynomial(pieces.map { it.first to it.second.antiderivative(algebra) }) - -/** - * Compute definite integral of given [PiecewisePolynomial] piece by piece in a given [range] - * Requires [UnivariateIntegrationNodes] or [IntegrationRange] and [IntegrandMaxCalls] - * - * TODO use context receiver for algebra - */ -@UnstableKMathAPI -public fun > PiecewisePolynomial.integrate( - algebra: Field, range: ClosedRange, -): T = algebra.sum( - pieces.map { (region, poly) -> - val intersectedRange = maxOf(range.start, region.start)..minOf(range.endInclusive, region.endInclusive) - //Check if polynomial range is not used - if (intersectedRange.start == intersectedRange.endInclusive) algebra.zero - else poly.integrate(algebra, intersectedRange) - } -) - -/** - * A generic spline-interpolation-based analytic integration - * * [IntegrationRange]—the univariate range of integration. By default, uses `0..1` interval. - * * [IntegrandMaxCalls]—the maximum number of function calls during integration. For non-iterative rules, always uses - * the maximum number of points. By default, uses 10 points. - */ -@UnstableKMathAPI -public class SplineIntegrator>( - public val algebra: Field, - public val bufferFactory: MutableBufferFactory, -) : UnivariateIntegrator { - override fun process(integrand: UnivariateIntegrand): UnivariateIntegrand = algebra { - val range = integrand.getFeature()?.range ?: 0.0..1.0 - - val interpolator: PolynomialInterpolator = SplineInterpolator(algebra, bufferFactory) - - val nodes: Buffer = integrand.getFeature()?.nodes ?: run { - val numPoints = integrand.getFeature()?.maxCalls ?: 100 - val step = (range.endInclusive - range.start) / (numPoints - 1) - DoubleBuffer(numPoints) { i -> range.start + i * step } - } - - val values = nodes.map(bufferFactory) { integrand.function(it) } - val polynomials = interpolator.interpolatePolynomials( - nodes.map(bufferFactory) { number(it) }, - values - ) - val res = polynomials.integrate(algebra, number(range.start)..number(range.endInclusive)) - integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + nodes.size) - } -} - -/** - * A simplified double-based spline-interpolation-based analytic integration - * * [IntegrationRange]—the univariate range of integration. By default, uses `0.0..1.0` interval. - * * [IntegrandMaxCalls]—the maximum number of function calls during integration. For non-iterative rules, always - * uses the maximum number of points. By default, uses 10 points. - */ -@UnstableKMathAPI -public object DoubleSplineIntegrator : UnivariateIntegrator { - override fun process(integrand: UnivariateIntegrand): UnivariateIntegrand { - val range = integrand.getFeature()?.range ?: 0.0..1.0 - val interpolator: PolynomialInterpolator = SplineInterpolator(DoubleField, ::DoubleBuffer) - - val nodes: Buffer = integrand.getFeature()?.nodes ?: run { - val numPoints = integrand.getFeature()?.maxCalls ?: 100 - val step = (range.endInclusive - range.start) / (numPoints - 1) - DoubleBuffer(numPoints) { i -> range.start + i * step } - } - - val values = nodes.map { integrand.function(it) } - val polynomials = interpolator.interpolatePolynomials(nodes, values) - val res = polynomials.integrate(DoubleField, range) - return integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + nodes.size) - } -} - -@Suppress("unused") -@UnstableKMathAPI -public inline val DoubleField.splineIntegrator: UnivariateIntegrator - get() = DoubleSplineIntegrator \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt deleted file mode 100644 index 5401be707..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt +++ /dev/null @@ -1,491 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.test.misc.* -import kotlin.test.* - - -class ListPolynomialTest { - @Test - fun test_Polynomial_Int_plus() { - RationalField.listPolynomial { - 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" - ) - assertEquals( - ListPolynomial(), - ListPolynomial() + 0, - "test 4" - ) - assertEquals( - ListPolynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), - ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + 1, - "test 5" - ) - assertEquals( - ListPolynomial(Rational(-1)), - ListPolynomial(Rational(-2)) + 1, - "test 6" - ) - assertEquals( - ListPolynomial(Rational(2)), - ListPolynomial() + 2, - "test 7" - ) - } - } - @Test - fun test_Polynomial_Int_minus() { - RationalField.listPolynomial { - 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" - ) - assertEquals( - ListPolynomial(), - ListPolynomial() - 0, - "test 4" - ) - assertEquals( - ListPolynomial(Rational(1), Rational(0), Rational(0), Rational(0)), - ListPolynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - 1, - "test 5" - ) - assertEquals( - ListPolynomial(Rational(1)), - ListPolynomial(Rational(2)) - 1, - "test 6" - ) - assertEquals( - ListPolynomial(Rational(-2)), - ListPolynomial() - 2, - "test 7" - ) - } - } - @Test - fun test_Polynomial_Int_times() { - IntModuloRing(35).listPolynomial { - 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" - ) - } - } - @Test - fun test_Int_Polynomial_plus() { - RationalField.listPolynomial { - 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" - ) - assertEquals( - ListPolynomial(), - 0 + ListPolynomial(), - "test 4" - ) - assertEquals( - ListPolynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), - 1 + ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), - "test 5" - ) - assertEquals( - ListPolynomial(Rational(-1)), - 1 + ListPolynomial(Rational(-2)), - "test 6" - ) - assertEquals( - ListPolynomial(Rational(2)), - 2 + ListPolynomial(), - "test 7" - ) - } - } - @Test - fun test_Int_Polynomial_minus() { - RationalField.listPolynomial { - 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(), - 0 - ListPolynomial(), - "test 4" - ) - assertEquals( - ListPolynomial(Rational(1), Rational(0), Rational(0), Rational(0)), - -1 - ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), - "test 5" - ) - assertEquals( - ListPolynomial(Rational(1)), - -1 - ListPolynomial(Rational(-2)), - "test 6" - ) - assertEquals( - ListPolynomial(Rational(-2)), - -2 - ListPolynomial(), - "test 7" - ) - } - } - @Test - fun test_Int_Polynomial_times() { - IntModuloRing(35).listPolynomial { - 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_Constant_plus() { - RationalField.listPolynomial { - 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.listPolynomial { - 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).listPolynomial { - 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.listPolynomial { - 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.listPolynomial { - 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).listPolynomial { - 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.listPolynomial { - 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.listPolynomial { - // (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.listPolynomial { - // (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).listPolynomial { - // (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-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt deleted file mode 100644 index c5eb8fb81..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.test.misc.Rational -import space.kscience.kmath.test.misc.RationalField -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith - - -class ListPolynomialUtilTest { - @Test - fun test_substitute_Double() { - 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_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_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 - fun test_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_nthDerivative() { - assertEquals( - ListPolynomial(Rational(-2), Rational(2)), - ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, 1), - "test 1" - ) - assertFailsWith("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_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_nthAntiderivative() { - assertEquals( - ListPolynomial(Rational(0), Rational(1), Rational(-1), Rational(1, 3)), - ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, 1), - "test 1" - ) - assertFailsWith("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 -- 2.34.1 From a2b02ef09e3b077b11db7023eb82882738ff5aca Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sat, 11 Jun 2022 16:15:59 +0300 Subject: [PATCH 075/275] Sifted rest usage of non-basic polynomial things. --- .../kmath/interpolation/Interpolator.kt | 92 ------------ .../kmath/interpolation/LinearInterpolator.kt | 43 ------ .../kmath/interpolation/SplineInterpolator.kt | 83 ---------- .../kmath/integration/SplineIntegralTest.kt | 48 ------ .../interpolation/LinearInterpolatorTest.kt | 29 ---- .../interpolation/SplineInterpolatorTest.kt | 31 ---- .../kscience/kmath/test/misc/IntModulo.kt | 142 ------------------ .../kscience/kmath/test/misc/Rational.kt | 135 ----------------- .../test/misc/RationalWithMemorization.kt | 107 ------------- .../kscience/kmath/test/misc/memorization.kt | 51 ------- .../space/kscience/kmath/test/misc/misc.kt | 31 ---- 11 files changed, 792 deletions(-) delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/RationalWithMemorization.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/memorization.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt deleted file mode 100644 index 62819be0c..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -@file:OptIn(UnstableKMathAPI::class) - -package space.kscience.kmath.interpolation - -import space.kscience.kmath.data.XYColumnarData -import space.kscience.kmath.functions.PiecewisePolynomial -import space.kscience.kmath.functions.asFunction -import space.kscience.kmath.functions.substitute -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.asBuffer - -/** - * And interpolator for data with x column type [X], y column type [Y]. - */ -public fun interface Interpolator { - public fun interpolate(points: XYColumnarData): (X) -> Y -} - -/** - * And interpolator returning [PiecewisePolynomial] function - */ -public interface PolynomialInterpolator> : Interpolator { - public val algebra: Ring - - public fun getDefaultValue(): T = error("Out of bounds") - - public fun interpolatePolynomials(points: XYColumnarData): PiecewisePolynomial - - override fun interpolate(points: XYColumnarData): (T) -> T = { x -> - interpolatePolynomials(points).substitute(algebra, x) ?: getDefaultValue() - } -} - - -public fun > PolynomialInterpolator.interpolatePolynomials( - x: Buffer, - y: Buffer, -): PiecewisePolynomial { - val pointSet = XYColumnarData.of(x, y) - return interpolatePolynomials(pointSet) -} - -public fun > PolynomialInterpolator.interpolatePolynomials( - data: Map, -): PiecewisePolynomial { - val pointSet = XYColumnarData.of(data.keys.toList().asBuffer(), data.values.toList().asBuffer()) - return interpolatePolynomials(pointSet) -} - -public fun > PolynomialInterpolator.interpolatePolynomials( - data: List>, -): PiecewisePolynomial { - val pointSet = XYColumnarData.of(data.map { it.first }.asBuffer(), data.map { it.second }.asBuffer()) - return interpolatePolynomials(pointSet) -} - -public fun > PolynomialInterpolator.interpolate( - x: Buffer, - y: Buffer, -): (T) -> T? = interpolatePolynomials(x, y).asFunction(algebra) - -public fun > PolynomialInterpolator.interpolate( - data: Map, -): (T) -> T? = interpolatePolynomials(data).asFunction(algebra) - -public fun > PolynomialInterpolator.interpolate( - data: List>, -): (T) -> T? = interpolatePolynomials(data).asFunction(algebra) - - -public fun > PolynomialInterpolator.interpolate( - x: Buffer, - y: Buffer, - defaultValue: T, -): (T) -> T = interpolatePolynomials(x, y).asFunction(algebra, defaultValue) - -public fun > PolynomialInterpolator.interpolate( - data: Map, - defaultValue: T, -): (T) -> T = interpolatePolynomials(data).asFunction(algebra, defaultValue) - -public fun > PolynomialInterpolator.interpolate( - data: List>, - defaultValue: T, -): (T) -> T = interpolatePolynomials(data).asFunction(algebra, defaultValue) \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt deleted file mode 100644 index b55f16cf2..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.interpolation - -import space.kscience.kmath.data.XYColumnarData -import space.kscience.kmath.functions.PiecewisePolynomial -import space.kscience.kmath.functions.ListPolynomial -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.Field -import space.kscience.kmath.operations.invoke - -@OptIn(UnstableKMathAPI::class) -internal fun > insureSorted(points: XYColumnarData<*, T, *>) { - for (i in 0 until points.size - 1) - require(points.x[i + 1] > points.x[i]) { "Input data is not sorted at index $i" } -} - -/** - * Reference JVM implementation: https://github.com/apache/commons-math/blob/master/src/main/java/org/apache/commons/math4/analysis/interpolation/LinearInterpolator.java - */ -public class LinearInterpolator>(override val algebra: Field) : PolynomialInterpolator { - - @OptIn(UnstableKMathAPI::class) - override fun interpolatePolynomials(points: XYColumnarData): PiecewisePolynomial = algebra { - require(points.size > 0) { "Point array should not be empty" } - insureSorted(points) - - PiecewisePolynomial(points.x[0]) { - for (i in 0 until points.size - 1) { - val slope = (points.y[i + 1] - points.y[i]) / (points.x[i + 1] - points.x[i]) - val const = points.y[i] - slope * points.x[i] - val polynomial = ListPolynomial(const, slope) - putRight(points.x[i + 1], polynomial) - } - } - } -} - -public val > Field.linearInterpolator: LinearInterpolator - get() = LinearInterpolator(this) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt deleted file mode 100644 index 48c90ff23..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.interpolation - -import space.kscience.kmath.data.XYColumnarData -import space.kscience.kmath.functions.PiecewisePolynomial -import space.kscience.kmath.functions.ListPolynomial -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.structures.DoubleBuffer -import space.kscience.kmath.structures.MutableBufferFactory - -/** - * Generic spline interpolator. Not recommended for performance critical places, use platform-specific and type - * specific ones. - * - * Based on - * https://github.com/apache/commons-math/blob/eb57d6d457002a0bb5336d789a3381a24599affe/src/main/java/org/apache/commons/math4/analysis/interpolation/SplineInterpolator.java - */ -public class SplineInterpolator>( - override val algebra: Field, - public val bufferFactory: MutableBufferFactory, -) : PolynomialInterpolator { - //TODO possibly optimize zeroed buffers - - @OptIn(UnstableKMathAPI::class) - override fun interpolatePolynomials(points: XYColumnarData): PiecewisePolynomial = algebra { - require(points.size >= 3) { "Can't use spline interpolator with less than 3 points" } - insureSorted(points) - // Number of intervals. The number of data points is n + 1. - val n = points.size - 1 - // Differences between knot points - val h = bufferFactory(n) { i -> points.x[i + 1] - points.x[i] } - val mu = bufferFactory(n) { zero } - val z = bufferFactory(n + 1) { zero } - - for (i in 1 until n) { - val g = 2.0 * (points.x[i + 1] - points.x[i - 1]) - h[i - 1] * mu[i - 1] - mu[i] = h[i] / g - z[i] = - ((points.y[i + 1] * h[i - 1] - points.y[i] * (points.x[i + 1] - points.x[i - 1]) + points.y[i - 1] * h[i]) * 3.0 / - (h[i - 1] * h[i]) - h[i - 1] * z[i - 1]) / g - } - - // cubic spline coefficients -- b is linear, c quadratic, d is cubic (original y's are constants) - - PiecewisePolynomial(points.x[points.size - 1]) { - var cOld = zero - - for (j in n - 1 downTo 0) { - val c = z[j] - mu[j] * cOld - val a = points.y[j] - val b = (points.y[j + 1] - points.y[j]) / h[j] - h[j] * (cOld + 2.0 * c) / 3.0 - val d = (cOld - c) / (3.0 * h[j]) - val x0 = points.x[j] - val x02 = x0 * x0 - val x03 = x02 * x0 - //Shift coefficients to represent absolute polynomial instead of one with an offset - val polynomial = ListPolynomial( - a - b * x0 + c * x02 - d * x03, - b - 2 * c * x0 + 3 * d * x02, - c - 3 * d * x0, - d - ) - cOld = c - putLeft(x0, polynomial) - } - } - } -} - - -public fun > Field.splineInterpolator( - bufferFactory: MutableBufferFactory, -): SplineInterpolator = SplineInterpolator(this, bufferFactory) - -public val DoubleField.splineInterpolator: SplineInterpolator - get() = SplineInterpolator(this, ::DoubleBuffer) \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt deleted file mode 100644 index aae0ad017..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.integration - -import space.kscience.kmath.functions.ListPolynomial -import space.kscience.kmath.functions.integrate -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.DoubleField -import kotlin.math.PI -import kotlin.math.sin -import kotlin.test.Test -import kotlin.test.assertEquals - -@OptIn(UnstableKMathAPI::class) -class SplineIntegralTest { - - @Test - fun integratePolynomial(){ - val polynomial = ListPolynomial(1.0, 2.0, 3.0) - val integral = polynomial.integrate(DoubleField,1.0..2.0) - assertEquals(11.0, integral, 0.001) - } - - @Test - fun gaussSin() { - val res = DoubleField.splineIntegrator.integrate(0.0..2 * PI, IntegrandMaxCalls(5)) { x -> - sin(x) - } - assertEquals(0.0, res.value, 1e-2) - } - - @Test - fun gaussUniform() { - val res = DoubleField.splineIntegrator.integrate(35.0..100.0, IntegrandMaxCalls(20)) { x -> - if(x in 30.0..50.0){ - 1.0 - } else { - 0.0 - } - } - assertEquals(15.0, res.value, 0.5) - } - - -} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt deleted file mode 100644 index 1143036d4..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.interpolation - -import space.kscience.kmath.operations.DoubleField -import kotlin.test.Test -import kotlin.test.assertEquals - -internal class LinearInterpolatorTest { - @Test - fun testInterpolation() { - val data = listOf( - 0.0 to 0.0, - 1.0 to 1.0, - 2.0 to 3.0, - 3.0 to 4.0 - ) - - //val polynomial: PiecewisePolynomial = DoubleField.linearInterpolator.interpolatePolynomials(data) - val function = DoubleField.linearInterpolator.interpolate(data) - assertEquals(null, function(-1.0)) - assertEquals(0.5, function(0.5)) - assertEquals(2.0, function(1.5)) - assertEquals(3.0, function(2.0)) - } -} diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt deleted file mode 100644 index 4c7d816d4..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.interpolation - -import space.kscience.kmath.operations.DoubleField -import kotlin.math.PI -import kotlin.math.sin -import kotlin.test.Test -import kotlin.test.assertEquals - -internal class SplineInterpolatorTest { - @Test - fun testInterpolation() { - val data = (0..10).map { - val x = it.toDouble() / 5 * PI - x to sin(x) - } - - //val polynomial: PiecewisePolynomial = DoubleField.splineInterpolator.interpolatePolynomials(data) - - val function = DoubleField.splineInterpolator.interpolate(data, Double.NaN) - - assertEquals(Double.NaN, function(-1.0)) - assertEquals(sin(0.5), function(0.5), 0.1) - assertEquals(sin(1.5), function(1.5), 0.1) - assertEquals(sin(2.0), function(2.0), 0.1) - } -} diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt deleted file mode 100644 index 2353beee6..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.test.misc - -import space.kscience.kmath.functions.ListPolynomial -import space.kscience.kmath.functions.ListPolynomialSpace -import space.kscience.kmath.misc.UnstableKMathAPI -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(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", "NOTHING_TO_INLINE") -@OptIn(UnstableKMathAPI::class) -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(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 -} - -fun ListPolynomialSpace.number(arg: Int) = IntModulo(arg, ring.modulus, toCheckInput = false) - -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) }) \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt deleted file mode 100644 index 72bb5942c..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.test.misc - -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.Field -import space.kscience.kmath.operations.NumbersAddOps - -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 = - Rational( - numerator * other.denominator + denominator * other.numerator, - denominator * other.denominator - ) - operator fun plus(other: Int): Rational = - Rational( - numerator + denominator * other.toLong(), - denominator - ) - operator fun plus(other: Long): Rational = - Rational( - numerator + denominator * other, - denominator - ) - operator fun minus(other: Rational): Rational = - Rational( - numerator * other.denominator - denominator * other.numerator, - denominator * other.denominator - ) - operator fun minus(other: Int): Rational = - Rational( - numerator - denominator * other.toLong(), - denominator - ) - operator fun minus(other: Long): Rational = - Rational( - numerator - denominator * other, - denominator - ) - operator fun times(other: Rational): Rational = - Rational( - numerator * other.numerator, - denominator * other.denominator - ) - operator fun times(other: Int): Rational = - Rational( - numerator * other.toLong(), - denominator - ) - operator fun times(other: Long): Rational = - Rational( - numerator * other, - denominator - ) - operator fun div(other: Rational): Rational = - Rational( - numerator * other.denominator, - denominator * other.numerator - ) - operator fun div(other: Int): Rational = - Rational( - numerator, - denominator * other.toLong() - ) - operator fun div(other: Long): Rational = - Rational( - numerator, - denominator * other - ) - 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", "NOTHING_TO_INLINE") -@OptIn(UnstableKMathAPI::class) -object RationalField : Field, NumbersAddOps { - override inline val zero: Rational get() = Rational.ZERO - override inline val one: Rational get() = Rational.ONE - - override inline fun number(value: Number): Rational = Rational(value.toLong()) - - override inline fun add(left: Rational, right: Rational): Rational = left + right - override inline fun multiply(left: Rational, right: Rational): Rational = left * right - override inline fun divide(left: Rational, right: Rational): Rational = left / right - override inline fun scale(a: Rational, value: Double): Rational = a * number(value) - - override inline fun Rational.unaryMinus(): Rational = -this - override inline fun Rational.plus(arg: Rational): Rational = this + arg - override inline fun Rational.minus(arg: Rational): Rational = this - arg - override inline fun Rational.times(arg: Rational): Rational = this * arg - override inline fun Rational.div(arg: Rational): Rational = this / arg -} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/RationalWithMemorization.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/RationalWithMemorization.kt deleted file mode 100644 index 05d9115fa..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/RationalWithMemorization.kt +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.test.misc - -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.* - -class RationalWithMemorization private constructor( - val value: Rational, - override val memory : OperationsMemory -): WithMemorization { - companion object { - /** - * Constant containing the zero (the additive identity) of the [Rational] field. - */ - public val ZERO: RationalWithMemorization = RationalWithMemorization(Rational.ZERO, object : Endpoint {}) - /** - * Constant containing the one (the multiplicative identity) of the [Rational] field. - */ - public val ONE: RationalWithMemorization = RationalWithMemorization(Rational.ONE, object : Endpoint {}) - } - constructor(numerator: Int, denominator: Int) : this(Rational(numerator, denominator), object : Endpoint {}) - constructor(numerator: Int, denominator: Long) : this(Rational(numerator, denominator), object : Endpoint {}) - constructor(numerator: Long, denominator: Int) : this(Rational(numerator, denominator), object : Endpoint {}) - constructor(numerator: Long, denominator: Long) : this(Rational(numerator, denominator), object : Endpoint {}) - constructor(numerator: Int) : this(Rational(numerator), object : Endpoint {}) - constructor(numerator: Long) : this(Rational(numerator), object : Endpoint {}) - - operator fun unaryPlus(): RationalWithMemorization = this - operator fun unaryMinus(): RationalWithMemorization = RationalWithMemorization( - -value, - object : Negation { - override val negated: OperationsMemory = memory - } - ) - operator fun plus(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization( - value + other.value, - object : Sum { - override val augend: OperationsMemory = memory - override val addend: OperationsMemory = other.memory - } - ) - operator fun minus(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization( - value - other.value, - object : Difference { - override val minuend: OperationsMemory = memory - override val subtrahend: OperationsMemory = other.memory - } - ) - operator fun times(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization( - value * other.value, - object : Product { - override val multiplicand: OperationsMemory = memory - override val multiplier: OperationsMemory = other.memory - } - ) - operator fun div(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization( - value / other.value, - object : Quotient { - override val dividend: OperationsMemory = memory - override val divisor: OperationsMemory = other.memory - } - ) - - override fun equals(other: Any?): Boolean = - other is RationalWithMemorization && value == other.value - - override fun hashCode(): Int = value.hashCode() - - override fun toString(): String = value.toString() -} - -@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -object RationalWithMemorizationRing : Ring { - override inline val zero: RationalWithMemorization get() = RationalWithMemorization.ZERO - override inline val one: RationalWithMemorization get() = RationalWithMemorization.ONE - - override inline fun add(left: RationalWithMemorization, right: RationalWithMemorization): RationalWithMemorization = left + right - override inline fun multiply(left: RationalWithMemorization, right: RationalWithMemorization): RationalWithMemorization = left * right - - override inline fun RationalWithMemorization.unaryMinus(): RationalWithMemorization = -this - override inline fun RationalWithMemorization.plus(arg: RationalWithMemorization): RationalWithMemorization = this + arg - override inline fun RationalWithMemorization.minus(arg: RationalWithMemorization): RationalWithMemorization = this - arg - override inline fun RationalWithMemorization.times(arg: RationalWithMemorization): RationalWithMemorization = this * arg -} - -@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -object RationalWithMemorizationField : Field { - override inline val zero: RationalWithMemorization get() = RationalWithMemorization.ZERO - override inline val one: RationalWithMemorization get() = RationalWithMemorization.ONE - - override inline fun number(value: Number): RationalWithMemorization = RationalWithMemorization(value.toLong()) - - override inline fun add(left: RationalWithMemorization, right: RationalWithMemorization): RationalWithMemorization = left + right - override inline fun multiply(left: RationalWithMemorization, right: RationalWithMemorization): RationalWithMemorization = left * right - override inline fun divide(left: RationalWithMemorization, right: RationalWithMemorization): RationalWithMemorization = left / right - override inline fun scale(a: RationalWithMemorization, value: Double): RationalWithMemorization = a * number(value) - - override inline fun RationalWithMemorization.unaryMinus(): RationalWithMemorization = -this - override inline fun RationalWithMemorization.plus(arg: RationalWithMemorization): RationalWithMemorization = this + arg - override inline fun RationalWithMemorization.minus(arg: RationalWithMemorization): RationalWithMemorization = this - arg - override inline fun RationalWithMemorization.times(arg: RationalWithMemorization): RationalWithMemorization = this * arg - override inline fun RationalWithMemorization.div(arg: RationalWithMemorization): RationalWithMemorization = this / arg -} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/memorization.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/memorization.kt deleted file mode 100644 index a4fb81274..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/memorization.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.test.misc - -sealed interface OperationsMemory - -interface Endpoint: OperationsMemory - -interface Negation: OperationsMemory { - val negated: OperationsMemory -} - -interface Sum: OperationsMemory { - val augend: OperationsMemory - val addend: OperationsMemory -} - -interface Difference: OperationsMemory { - val minuend: OperationsMemory - val subtrahend: OperationsMemory -} - -interface Product: OperationsMemory { - val multiplicand: OperationsMemory - val multiplier: OperationsMemory -} - -interface Quotient: OperationsMemory { - val dividend: OperationsMemory - val divisor: OperationsMemory -} - - -fun equalMemories(one: OperationsMemory, other: OperationsMemory) : Boolean = - when(one) { - is Negation -> other is Negation && equalMemories(one.negated, other.negated) - is Sum -> other is Sum && equalMemories(one.augend, other.augend) && equalMemories(one.addend, other.addend) - is Difference -> other is Difference && equalMemories(one.minuend, other.minuend) && equalMemories(one.subtrahend, other.subtrahend) - is Product -> other is Product && equalMemories(one.multiplicand, other.multiplicand) && equalMemories(one.multiplier, other.multiplier) - is Quotient -> other is Quotient && equalMemories(one.dividend, other.dividend) && equalMemories(one.divisor, other.divisor) - is Endpoint -> one === other - } - -interface WithMemorization { - val memory: OperationsMemory -} - -fun equalMemories(one: WithMemorization, other: WithMemorization) : Boolean = equalMemories(one.memory, other.memory) \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt deleted file mode 100644 index cc647fa2c..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.test.misc - -// TODO: Move to corresponding module "kmath-number-theory" - -import kotlin.math.abs - - -data class BezoutIdentityWithGCD(val first: T, val second: T, val gcd: T) - -tailrec fun gcd(a: Long, b: Long): Long = if (a == 0L) abs(b) else gcd(b % a, a) - -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 -- 2.34.1 From 8af183a969e2099cea5d3c293be319e7aa1b0080 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sat, 11 Jun 2022 19:22:57 +0300 Subject: [PATCH 076/275] Fixed typos. Added docstrings. Added variable convertional methods. --- .../kscience/kmath/functions/Polynomial.kt | 150 ++++-- .../kmath/functions/RationalFunction.kt | 467 +++++++++++++----- 2 files changed, 468 insertions(+), 149 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index e201f1f6e..f2eba10d5 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -25,38 +25,38 @@ public interface Polynomial @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 constant (member of underlying 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]. */ public operator fun C.plus(other: Int): C /** - * Returns difference between the constant and the integer represented as constant (member of underlying ring). + * 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]. */ public operator fun C.minus(other: Int): C /** - * Returns product of the constant and the integer represented as constant (member of underlying ring). + * 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]. */ public operator fun C.times(other: Int): C /** - * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public operator fun Int.plus(other: C): C /** - * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public operator fun Int.minus(other: C): C /** - * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ @@ -72,38 +72,38 @@ public interface PolynomialSpace> : Ring

{ public fun Int.asConstant(): C = constantNumber(this) /** - * Returns sum of the polynomial and the integer represented as polynomial. + * 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 polynomial. + * 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 polynomial. + * 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 polynomial and the polynomial. + * 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 polynomial and the polynomial. + * 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 polynomial and the polynomial. + * Returns product of the integer represented as a polynomial and the polynomial. * * The operation is equivalent to sum of [this] copies of [other]. */ @@ -165,28 +165,28 @@ public interface PolynomialSpace> : Ring

{ public val constantOne: C /** - * Returns sum of the constant represented as polynomial and the polynomial. + * Returns sum of the constant represented as a polynomial and the polynomial. */ public operator fun C.plus(other: P): P /** - * Returns difference between the constant represented as polynomial and the polynomial. + * Returns difference between the constant represented as a polynomial and the polynomial. */ public operator fun C.minus(other: P): P /** - * Returns product of the constant represented as polynomial and the polynomial. + * Returns product of the constant represented as a polynomial and the polynomial. */ public operator fun C.times(other: P): P /** - * Returns sum of the constant represented as polynomial and the polynomial. + * Returns sum of the constant represented as a polynomial and the polynomial. */ public operator fun P.plus(other: C): P /** - * Returns difference between the constant represented as polynomial and the polynomial. + * Returns difference between the constant represented as a polynomial and the polynomial. */ public operator fun P.minus(other: C): P /** - * Returns product of the constant represented as polynomial and the polynomial. + * Returns product of the constant represented as a polynomial and the polynomial. */ public operator fun P.times(other: C): P @@ -254,41 +254,44 @@ public interface PolynomialSpace> : Ring

{ @Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 public interface PolynomialSpaceOverRing, A: Ring> : 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 constant (member of underlying 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]. */ 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 constant (member of underlying ring). + * 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]. */ 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 constant (member of underlying ring). + * 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]. */ public override operator fun C.times(other: Int): C = ring { multiplyByDoubling(this@times, other) } /** - * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public override operator fun Int.plus(other: C): C = ring { addMultipliedByDoubling(other, one, this@plus) } /** - * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public override operator fun Int.minus(other: C): C = ring { addMultipliedByDoubling(-other, one, this@minus) } /** - * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ @@ -330,58 +333,143 @@ public interface PolynomialSpaceOverRing, A: Ring> : Poly 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") 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") 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") 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") 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") 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") public operator fun Int.times(other: V): P - @JvmName("plusConstantVariable") - public operator fun C.plus(other: V): P - @JvmName("minusConstantVariable") - public operator fun C.minus(other: V): P - @JvmName("timesConstantVariable") - public operator fun C.times(other: V): P - + /** + * Returns sum of the variable represented as a monic monomial and the constant represented as a constant polynomial. + */ @JvmName("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") 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") 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") + 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") + 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") + 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. + */ + public fun number(variable: V): P = +variable + /** + * Represents the variable as a monic monomial. + */ + 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 diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index dfec126f3..edc9dfa5c 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -25,44 +25,44 @@ public interface RationalFunction> { * [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 in them. + * @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 RationalFunctionalSpace, R: RationalFunction> : Ring { /** - * Returns sum of the constant and the integer represented as constant (member of underlying 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]. */ public operator fun C.plus(other: Int): C /** - * Returns difference between the constant and the integer represented as constant (member of underlying ring). + * 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]. */ public operator fun C.minus(other: Int): C /** - * Returns product of the constant and the integer represented as constant (member of underlying ring). + * 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]. */ public operator fun C.times(other: Int): C /** - * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public operator fun Int.plus(other: C): C /** - * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public operator fun Int.minus(other: C): C /** - * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ @@ -78,38 +78,38 @@ public interface RationalFunctionalSpace, R: RationalFunctio public fun Int.asConstant(): C = constantNumber(this) /** - * Returns sum of the constant and the integer represented as polynomial. + * 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]. */ public operator fun P.plus(other: Int): P /** - * Returns difference between the constant and the integer represented as polynomial. + * 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]. */ public operator fun P.minus(other: Int): P /** - * Returns product of the constant and the integer represented as polynomial. + * Returns product of the constant 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 /** - * Returns sum of the integer represented as polynomial and the constant. + * 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]. */ public operator fun Int.plus(other: P): P /** - * Returns difference between the integer represented as polynomial and the constant. + * 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]. */ public operator fun Int.minus(other: P): P /** - * Returns product of the integer represented as polynomial and the constant. + * Returns product of the integer represented as a polynomial and the constant. * * The operation is equivalent to sum of [this] copies of [other]. */ @@ -125,25 +125,25 @@ public interface RationalFunctionalSpace, R: RationalFunctio public fun Int.asPolynomial(): P = polynomialNumber(this) /** - * Returns sum of the rational function and the integer represented as rational function. + * 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 rational function. + * 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 rational function. + * 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 rational function. + * 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]. @@ -151,25 +151,25 @@ public interface RationalFunctionalSpace, R: RationalFunctio public operator fun R.div(other: Int): R = this / multiplyByDoubling(one, other) /** - * Returns sum of the integer represented as rational function and the rational function. + * 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 rational function and the rational function. + * 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 rational function and the rational function. + * 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 rational function and the rational function. + * 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. @@ -232,28 +232,28 @@ public interface RationalFunctionalSpace, R: RationalFunctio public val constantOne: C /** - * Returns sum of the constant represented as polynomial and the polynomial. + * Returns sum of the constant represented as a polynomial and the polynomial. */ public operator fun C.plus(other: P): P /** - * Returns difference between the constant represented as polynomial and the polynomial. + * Returns difference between the constant represented as a polynomial and the polynomial. */ public operator fun C.minus(other: P): P /** - * Returns product of the constant represented as polynomial and the polynomial. + * Returns product of the constant represented as a polynomial and the polynomial. */ public operator fun C.times(other: P): P /** - * Returns sum of the constant represented as polynomial and the polynomial. + * Returns sum of the constant represented as a polynomial and the polynomial. */ public operator fun P.plus(other: C): P /** - * Returns difference between the constant represented as polynomial and the polynomial. + * Returns difference between the constant represented as a polynomial and the polynomial. */ public operator fun P.minus(other: C): P /** - * Returns product of the constant represented as polynomial and the polynomial. + * Returns product of the constant represented as a polynomial and the polynomial. */ public operator fun P.times(other: C): P @@ -305,36 +305,36 @@ public interface RationalFunctionalSpace, R: RationalFunctio public val polynomialOne: P /** - * Returns sum of the constant represented as rational function and the rational function. + * Returns sum of the constant represented as a rational function and the rational function. */ public operator fun C.plus(other: R): R /** - * Returns difference between the constant represented as polynomial and the rational function. + * Returns difference between the constant represented as a polynomial and the rational function. */ public operator fun C.minus(other: R): R /** - * Returns product of the constant represented as polynomial and the rational function. + * Returns product of the constant represented as a polynomial and the rational function. */ public operator fun C.times(other: R): R /** - * Returns quotient of the constant represented as polynomial and the rational function. + * Returns quotient of the constant represented as a polynomial and the rational function. */ public operator fun C.div(other: R): R /** - * Returns sum of the rational function and the constant represented as rational function. + * Returns sum of the rational function and the constant represented as a rational function. */ public operator fun R.plus(other: C): R /** - * Returns difference between the rational function and the constant represented as rational function. + * Returns difference between the rational function and the constant represented as a rational function. */ public operator fun R.minus(other: C): R /** - * Returns product of the rational function and the constant represented as rational function. + * Returns product of the rational function and the constant represented as a rational function. */ public operator fun R.times(other: C): R /** - * Returns quotient of the rational function and the constant represented as rational function. + * Returns quotient of the rational function and the constant represented as a rational function. */ public operator fun R.div(other: C): R @@ -348,36 +348,36 @@ public interface RationalFunctionalSpace, R: RationalFunctio public fun C.asRationalFunction(): R = number(this) /** - * Returns sum of the polynomial represented as rational function and the rational function. + * Returns sum of the polynomial represented as a rational function and the rational function. */ public operator fun P.plus(other: R): R /** - * Returns difference between the polynomial represented as polynomial and the rational function. + * Returns difference between the polynomial represented as a polynomial and the rational function. */ public operator fun P.minus(other: R): R /** - * Returns product of the polynomial represented as polynomial and the rational function. + * Returns product of the polynomial represented as a polynomial and the rational function. */ public operator fun P.times(other: R): R /** - * Returns quotient of the polynomial represented as polynomial and the rational function. + * Returns quotient of the polynomial represented as a polynomial and the rational function. */ public operator fun P.div(other: R): R /** - * Returns sum of the rational function and the polynomial represented as rational function. + * Returns sum of the rational function and the polynomial represented as a rational function. */ public operator fun R.plus(other: P): R /** - * Returns difference between the rational function and the polynomial represented as rational function. + * Returns difference between the rational function and the polynomial represented as a rational function. */ public operator fun R.minus(other: P): R /** - * Returns product of the rational function and the polynomial represented as rational function. + * Returns product of the rational function and the polynomial represented as a rational function. */ public operator fun R.times(other: P): R /** - * Returns quotient of the rational function and the polynomial represented as rational function. + * Returns quotient of the rational function and the polynomial represented as a rational function. */ public operator fun R.div(other: P): R @@ -459,43 +459,51 @@ public interface RationalFunctionalSpace, R: RationalFunctio * @param A the type of algebraic structure (precisely, of ring) provided for constants. */ @Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 -public interface RationalFunctionalSpaceOverRing, R: RationalFunction, A: Ring> : RationalFunctionalSpace { +public interface RationalFunctionalSpaceOverRing< + C, + P: Polynomial, + R: RationalFunction, + A: Ring + > : RationalFunctionalSpace { + /** + * 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 constant (member of underlying 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]. */ 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 constant (member of underlying ring). + * 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]. */ 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 constant (member of underlying ring). + * 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]. */ public override operator fun C.times(other: Int): C = ring { multiplyByDoubling(this@times, other) } /** - * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public override operator fun Int.plus(other: C): C = ring { addMultipliedByDoubling(other, one, this@plus) } /** - * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public override operator fun Int.minus(other: C): C = ring { addMultipliedByDoubling(-other, one, this@minus) } /** - * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ @@ -560,41 +568,44 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< AP: PolynomialSpace, > : RationalFunctionalSpace { + /** + * 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 constant (member of underlying 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]. */ public override operator fun C.plus(other: Int): C = polynomialRing { this@plus + other } /** - * Returns difference between the constant and the integer represented as constant (member of underlying ring). + * 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]. */ public override operator fun C.minus(other: Int): C = polynomialRing { this@minus - other } /** - * Returns product of the constant and the integer represented as constant (member of underlying ring). + * 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]. */ public override operator fun C.times(other: Int): C = polynomialRing { this@times * other } /** - * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public override operator fun Int.plus(other: C): C = polynomialRing { this@plus + other } /** - * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public override operator fun Int.minus(other: C): C = polynomialRing { this@minus - other } /** - * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ @@ -610,38 +621,38 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< override fun Int.asConstant(): C = polynomialRing { asConstant() } /** - * Returns sum of the constant and the integer represented as polynomial. + * 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]. */ public override operator fun P.plus(other: Int): P = polynomialRing { this@plus + other } /** - * Returns difference between the constant and the integer represented as polynomial. + * 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]. */ public override operator fun P.minus(other: Int): P = polynomialRing { this@minus - other } /** - * Returns product of the constant and the integer represented as polynomial. + * Returns product of the constant and the integer represented as a polynomial. * * The operation is equivalent to sum of [other] copies of [this]. */ public override operator fun P.times(other: Int): P = polynomialRing { this@times * other } /** - * Returns sum of the integer represented as polynomial and the constant. + * 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]. */ public override operator fun Int.plus(other: P): P = polynomialRing { this@plus + other } /** - * Returns difference between the integer represented as polynomial and the constant. + * 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]. */ public override operator fun Int.minus(other: P): P = polynomialRing { this@minus - other } /** - * Returns product of the integer represented as polynomial and the constant. + * Returns product of the integer represented as a polynomial and the constant. * * The operation is equivalent to sum of [this] copies of [other]. */ @@ -697,28 +708,28 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< public override val constantOne: C get() = polynomialRing.constantOne /** - * Returns sum of the constant represented as polynomial and the polynomial. + * Returns sum of the constant represented as a polynomial and the polynomial. */ public override operator fun C.plus(other: P): P = polynomialRing { this@plus + other } /** - * Returns difference between the constant represented as polynomial and the polynomial. + * Returns difference between the constant represented as a polynomial and the polynomial. */ public override operator fun C.minus(other: P): P = polynomialRing { this@minus - other } /** - * Returns product of the constant represented as polynomial and the polynomial. + * Returns product of the constant represented as a polynomial and the polynomial. */ public override operator fun C.times(other: P): P = polynomialRing { this@times * other } /** - * Returns sum of the constant represented as polynomial and the polynomial. + * Returns sum of the constant represented as a polynomial and the polynomial. */ public override operator fun P.plus(other: C): P = polynomialRing { this@plus + other } /** - * Returns difference between the constant represented as polynomial and the polynomial. + * Returns difference between the constant represented as a polynomial and the polynomial. */ public override operator fun P.minus(other: C): P = polynomialRing { this@minus - other } /** - * Returns product of the constant represented as polynomial and the polynomial. + * Returns product of the constant represented as a polynomial and the polynomial. */ public override operator fun P.times(other: C): P = polynomialRing { this@times * other } @@ -774,7 +785,8 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< /** * 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 + * [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. @@ -786,10 +798,14 @@ public abstract class PolynomialSpaceOfFractions< P: Polynomial, R: RationalFunction, > : RationalFunctionalSpace { + + /** + * 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 rational function. + * 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]. */ @@ -799,7 +815,7 @@ public abstract class PolynomialSpaceOfFractions< denominator ) /** - * Returns difference between the rational function and the integer represented as rational function. + * 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]. */ @@ -809,7 +825,7 @@ public abstract class PolynomialSpaceOfFractions< denominator ) /** - * Returns product of the rational function and the integer represented as rational function. + * 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]. */ @@ -826,7 +842,7 @@ public abstract class PolynomialSpaceOfFractions< ) /** - * Returns sum of the integer represented as rational function and the rational function. + * 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]. */ @@ -836,7 +852,7 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) /** - * Returns difference between the integer represented as rational function and the rational function. + * 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]. */ @@ -846,7 +862,7 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) /** - * Returns product of the integer represented as rational function and the rational function. + * 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]. */ @@ -873,7 +889,7 @@ public abstract class PolynomialSpaceOfFractions< public override operator fun P.div(other: P): R = constructRationalFunction(this, other) /** - * Returns sum of the constant represented as rational function and the rational function. + * Returns sum of the constant represented as a rational function and the rational function. */ public override operator fun C.plus(other: R): R = constructRationalFunction( @@ -881,7 +897,7 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) /** - * Returns difference between the constant represented as polynomial and the rational function. + * Returns difference between the constant represented as a polynomial and the rational function. */ public override operator fun C.minus(other: R): R = constructRationalFunction( @@ -889,7 +905,7 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) /** - * Returns product of the constant represented as polynomial and the rational function. + * Returns product of the constant represented as a polynomial and the rational function. */ public override operator fun C.times(other: R): R = constructRationalFunction( @@ -904,7 +920,7 @@ public abstract class PolynomialSpaceOfFractions< ) /** - * Returns sum of the constant represented as rational function and the rational function. + * Returns sum of the constant represented as a rational function and the rational function. */ public override operator fun R.plus(other: C): R = constructRationalFunction( @@ -912,7 +928,7 @@ public abstract class PolynomialSpaceOfFractions< denominator ) /** - * Returns difference between the constant represented as rational function and the rational function. + * Returns difference between the constant represented as a rational function and the rational function. */ public override operator fun R.minus(other: C): R = constructRationalFunction( @@ -920,7 +936,7 @@ public abstract class PolynomialSpaceOfFractions< denominator ) /** - * Returns product of the constant represented as rational function and the rational function. + * Returns product of the constant represented as a rational function and the rational function. */ public override operator fun R.times(other: C): R = constructRationalFunction( @@ -940,7 +956,7 @@ public abstract class PolynomialSpaceOfFractions< public override fun number(value: C): R = constructRationalFunction(polynomialNumber(value)) /** - * Returns sum of the polynomial represented as rational function and the rational function. + * Returns sum of the polynomial represented as a rational function and the rational function. */ public override operator fun P.plus(other: R): R = constructRationalFunction( @@ -948,7 +964,7 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) /** - * Returns difference between the polynomial represented as polynomial and the rational function. + * Returns difference between the polynomial represented as a polynomial and the rational function. */ public override operator fun P.minus(other: R): R = constructRationalFunction( @@ -956,7 +972,7 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) /** - * Returns product of the polynomial represented as polynomial and the rational function. + * Returns product of the polynomial represented as a polynomial and the rational function. */ public override operator fun P.times(other: R): R = constructRationalFunction( @@ -971,7 +987,7 @@ public abstract class PolynomialSpaceOfFractions< ) /** - * Returns sum of the polynomial represented as rational function and the rational function. + * Returns sum of the polynomial represented as a rational function and the rational function. */ public override operator fun R.plus(other: P): R = constructRationalFunction( @@ -979,7 +995,7 @@ public abstract class PolynomialSpaceOfFractions< denominator ) /** - * Returns difference between the polynomial represented as rational function and the rational function. + * Returns difference between the polynomial represented as a rational function and the rational function. */ public override operator fun R.minus(other: P): R = constructRationalFunction( @@ -987,7 +1003,7 @@ public abstract class PolynomialSpaceOfFractions< denominator ) /** - * Returns product of the polynomial represented as rational function and the rational function. + * Returns product of the polynomial represented as a rational function and the rational function. */ public override operator fun R.times(other: P): R = constructRationalFunction( @@ -1052,6 +1068,15 @@ public abstract class PolynomialSpaceOfFractions< public override val one: R get() = 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 MultivariateRationalFunctionalSpace< C, @@ -1059,70 +1084,175 @@ public interface MultivariateRationalFunctionalSpace< P: Polynomial, R: RationalFunction >: RationalFunctionalSpace { + /** + * Returns sum of the variable represented as a monic monomial and the integer represented as a constant polynomial. + */ @JvmName("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") 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") 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") 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") 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") public operator fun Int.times(other: V): P - @JvmName("plusConstantVariable") - public operator fun C.plus(other: V): P - @JvmName("minusConstantVariable") - public operator fun C.minus(other: V): P - @JvmName("timesConstantVariable") - public operator fun C.times(other: V): P - + /** + * Returns sum of the variable represented as a monic monomial and the constant represented as a constant polynomial. + */ @JvmName("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") 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") 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") + 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") + 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") + 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. + */ + public fun polynomialNumber(variable: V): P = +variable + /** + * Represents the variable as a monic monomial. + */ + public fun V.asPolynomial(): P = polynomialNumber(this) + + /** + * Represents the [variable] as a rational function. + */ + public fun number(variable: V): R = number(polynomialNumber(variable)) + /** + * Represents the variable as a rational function. + */ + 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 @@ -1161,22 +1291,17 @@ public interface MultivariateRationalFunctionalSpace< public val R.countOfVariables: Int get() = variables.size } -public interface MultivariateRationalFunctionalSpaceOverRing< - C, - V, - P: Polynomial, - R: RationalFunction, - A: Ring - > : RationalFunctionalSpaceOverRing, MultivariateRationalFunctionalSpace - -public interface MultivariateRationalFunctionalSpaceOverPolynomialSpace< - C, - V, - P: Polynomial, - R: RationalFunction, - AP: PolynomialSpace, - > : RationalFunctionalSpaceOverPolynomialSpace, MultivariateRationalFunctionalSpace - +/** + * 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 MultivariateRationalFunctionalSpaceOverMultivariatePolynomialSpace< C, @@ -1184,57 +1309,135 @@ public interface MultivariateRationalFunctionalSpaceOverMultivariatePolynomialSp P: Polynomial, R: RationalFunction, AP: MultivariatePolynomialSpace, - > : MultivariateRationalFunctionalSpaceOverPolynomialSpace { + > : RationalFunctionalSpaceOverPolynomialSpace, MultivariateRationalFunctionalSpace { + /** + * 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 } - @JvmName("plusConstantVariable") - public override operator fun C.plus(other: V): P = polynomialRing { this@plus + other } - @JvmName("minusConstantVariable") - public override operator fun C.minus(other: V): P = polynomialRing { this@minus - other } - @JvmName("timesConstantVariable") - public override operator fun C.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. + */ + public override fun polynomialNumber(variable: V): P = polynomialRing { number(variable) } + /** + * Represents the variable as a monic monomial. + */ + 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 } @@ -1264,6 +1467,16 @@ public interface MultivariateRationalFunctionalSpaceOverMultivariatePolynomialSp 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, @@ -1271,18 +1484,27 @@ public abstract class MultivariatePolynomialSpaceOfFractions< P: Polynomial, R: RationalFunction, > : MultivariateRationalFunctionalSpace, 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( @@ -1290,18 +1512,27 @@ public abstract class MultivariatePolynomialSpaceOfFractions< 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. + */ @JvmName("timesRationalVariable") public override operator fun R.times(other: V): R = constructRationalFunction( -- 2.34.1 From 03b92de6e0803c0813bf53469cf9d195699f016a Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sat, 11 Jun 2022 19:29:14 +0300 Subject: [PATCH 077/275] Sifted ListPolynomial's basics. --- .../kmath/functions/LabeledPolynomial.kt | 539 ------------------ .../functions/LabeledRationalFunction.kt | 139 ----- .../kmath/functions/NumberedPolynomial.kt | 389 ------------- .../functions/NumberedRationalFunction.kt | 188 ------ .../kscience/kmath/functions/Piecewise.kt | 132 ----- .../kmath/functions/labeledConstructors.kt | 203 ------- .../kmath/functions/labeledPolynomialUtil.kt | 495 ---------------- .../functions/labeledRationalFunctionUtil.kt | 33 -- .../kmath/functions/numberedConstructors.kt | 195 ------- .../kmath/functions/numberedPolynomialUtil.kt | 528 ----------------- .../functions/numberedRationalFunctionUtil.kt | 33 -- .../kmath/integration/SplineIntegrator.kt | 107 ---- .../kmath/interpolation/Interpolator.kt | 92 --- .../kmath/interpolation/LinearInterpolator.kt | 43 -- .../kmath/interpolation/SplineInterpolator.kt | 83 --- .../kmath/integration/SplineIntegralTest.kt | 48 -- .../interpolation/LinearInterpolatorTest.kt | 29 - .../interpolation/SplineInterpolatorTest.kt | 31 - .../kscience/kmath/test/misc/IntModulo.kt | 142 ----- .../kscience/kmath/test/misc/Rational.kt | 135 ----- .../test/misc/RationalWithMemorization.kt | 107 ---- .../kscience/kmath/test/misc/memorization.kt | 51 -- .../space/kscience/kmath/test/misc/misc.kt | 31 - 23 files changed, 3773 deletions(-) delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/RationalWithMemorization.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/memorization.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt deleted file mode 100644 index b904f7331..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ /dev/null @@ -1,539 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.ScaleOperations -import kotlin.math.max - - -/** - * Represents multivariate polynomials with labeled variables. - * - * @param C Ring in which the polynomial is considered. - */ -public data class LabeledPolynomial -internal constructor( - /** - * Map that collects coefficients of the polynomial. Every non-zero monomial - * `a x_1^{d_1} ... x_n^{d_n}` is represented as pair "key-value" in the map, where value is coefficients `a` and - * key is map that associates variables in the monomial with multiplicity of them occurring in the monomial. - * For example polynomial - * ``` - * 5 a^2 c^3 - 6 b + 0 b c - * ``` - * has coefficients represented as - * ``` - * mapOf( - * mapOf( - * a to 2, - * c to 3 - * ) to 5, - * mapOf( - * b to 1 - * ) to (-6) - * ) - * ``` - * where `a`, `b` and `c` are corresponding [Symbol] objects. - */ - public val coefficients: Map, C> -) : Polynomial { - override fun toString(): String = "LabeledPolynomial$coefficients" -} - -/** - * Space of polynomials. - * - * @param C the type of operated polynomials. - * @param A the intersection of [Ring] of [C] and [ScaleOperations] of [C]. - * @param ring the [A] instance. - */ -public class LabeledPolynomialSpace>( - public override val ring: A, -) : MultivariatePolynomialSpace>, PolynomialSpaceOverRing, A> { - public override operator fun Symbol.plus(other: Int): LabeledPolynomial = - if (other == 0) LabeledPolynomial(mapOf( - mapOf(this@plus to 1U) to constantOne, - )) - else LabeledPolynomial(mapOf( - mapOf(this@plus to 1U) to constantOne, - emptyMap() to constantOne * other, - )) - public override operator fun Symbol.minus(other: Int): LabeledPolynomial = - if (other == 0) LabeledPolynomial(mapOf( - mapOf(this@minus to 1U) to -constantOne, - )) - else LabeledPolynomial(mapOf( - mapOf(this@minus to 1U) to -constantOne, - emptyMap() to constantOne * other, - )) - public override operator fun Symbol.times(other: Int): LabeledPolynomial = - if (other == 0) zero - else LabeledPolynomial(mapOf( - mapOf(this to 1U) to constantOne * other, - )) - - public override operator fun Int.plus(other: Symbol): LabeledPolynomial = - if (this == 0) LabeledPolynomial(mapOf( - mapOf(other to 1U) to constantOne, - )) - else LabeledPolynomial(mapOf( - mapOf(other to 1U) to constantOne, - emptyMap() to constantOne * this@plus, - )) - public override operator fun Int.minus(other: Symbol): LabeledPolynomial = - if (this == 0) LabeledPolynomial(mapOf( - mapOf(other to 1U) to -constantOne, - )) - else LabeledPolynomial(mapOf( - mapOf(other to 1U) to -constantOne, - emptyMap() to constantOne * this@minus, - )) - public override operator fun Int.times(other: Symbol): LabeledPolynomial = - if (this == 0) zero - else LabeledPolynomial(mapOf( - mapOf(other to 1U) to constantOne * this@times, - )) - - /** - * Returns sum of the polynomial and the integer represented as polynomial. - * - * The operation is equivalent to adding [other] copies of unit polynomial to [this]. - */ - public override operator fun LabeledPolynomial.plus(other: Int): LabeledPolynomial = - if (other == 0) this - else with(coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to other.asConstant())) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = emptyMap() - - this[degs] = getOrElse(degs) { constantZero } + other - } - ) - } - /** - * Returns difference between the polynomial and the integer represented as polynomial. - * - * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. - */ - public override operator fun LabeledPolynomial.minus(other: Int): LabeledPolynomial = - if (other == 0) this - else with(coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to (-other).asConstant())) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = emptyMap() - - this[degs] = getOrElse(degs) { constantZero } - other - } - ) - } - /** - * Returns product of the polynomial and the integer represented as polynomial. - * - * The operation is equivalent to sum of [other] copies of [this]. - */ - public override operator fun LabeledPolynomial.times(other: Int): LabeledPolynomial = - if (other == 0) zero - else LabeledPolynomial( - coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this[degs]!! * other - } - ) - - /** - * Returns sum of the integer represented as 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 = - if (this == 0) other - else with(other.coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@plus.asConstant())) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = emptyMap() - - this[degs] = this@plus + getOrElse(degs) { constantZero } - } - ) - } - /** - * Returns difference between the integer represented as 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 = - if (this == 0) other - else with(other.coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@minus.asConstant())) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = emptyMap() - - this[degs] = this@minus - getOrElse(degs) { constantZero } - } - ) - } - /** - * Returns product of the integer represented as polynomial and the polynomial. - * - * The operation is equivalent to sum of [this] copies of [other]. - */ - public override operator fun Int.times(other: LabeledPolynomial): LabeledPolynomial = - if (this == 0) zero - else LabeledPolynomial( - other.coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this@times * this[degs]!! - } - ) - - /** - * Converts the integer [value] to polynomial. - */ - public override fun number(value: Int): LabeledPolynomial = number(constantNumber(value)) - - public override operator fun C.plus(other: Symbol): LabeledPolynomial = - LabeledPolynomial(mapOf( - mapOf(other to 1U) to constantOne, - emptyMap() to this@plus, - )) - public override operator fun C.minus(other: Symbol): LabeledPolynomial = - LabeledPolynomial(mapOf( - mapOf(other to 1U) to -constantOne, - emptyMap() to this@minus, - )) - public override operator fun C.times(other: Symbol): LabeledPolynomial = - LabeledPolynomial(mapOf( - mapOf(other to 1U) to this@times, - )) - - public override operator fun Symbol.plus(other: C): LabeledPolynomial = - LabeledPolynomial(mapOf( - mapOf(this@plus to 1U) to constantOne, - emptyMap() to other, - )) - public override operator fun Symbol.minus(other: C): LabeledPolynomial = - LabeledPolynomial(mapOf( - mapOf(this@minus to 1U) to -constantOne, - emptyMap() to other, - )) - public override operator fun Symbol.times(other: C): LabeledPolynomial = - LabeledPolynomial(mapOf( - mapOf(this@times to 1U) to other, - )) - - /** - * Returns sum of the constant represented as polynomial and the polynomial. - */ - override operator fun C.plus(other: LabeledPolynomial): LabeledPolynomial = - with(other.coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@plus)) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = emptyMap() - - this[degs] = this@plus + getOrElse(degs) { constantZero } - } - ) - } - /** - * Returns difference between the constant represented as polynomial and the polynomial. - */ - override operator fun C.minus(other: LabeledPolynomial): LabeledPolynomial = - with(other.coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@minus)) - else LabeledPolynomial( - toMutableMap() - .apply { - forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } - - val degs = emptyMap() - - this[degs] = this@minus - getOrElse(degs) { constantZero } - } - ) - } - /** - * Returns product of the constant represented as polynomial and the polynomial. - */ - override operator fun C.times(other: LabeledPolynomial): LabeledPolynomial = - LabeledPolynomial( - other.coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this@times * this[degs]!! - } - ) - - /** - * Returns sum of the constant represented as polynomial and the polynomial. - */ - override operator fun LabeledPolynomial.plus(other: C): LabeledPolynomial = - with(coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to other)) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = emptyMap() - - this[degs] = getOrElse(degs) { constantZero } + other - } - ) - } - /** - * Returns difference between the constant represented as polynomial and the polynomial. - */ - override operator fun LabeledPolynomial.minus(other: C): LabeledPolynomial = - with(coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to other)) - else LabeledPolynomial( - toMutableMap() - .apply { - forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } - - val degs = emptyMap() - - this[degs] = getOrElse(degs) { constantZero } - other - } - ) - } - /** - * Returns product of the constant represented as polynomial and the polynomial. - */ - override operator fun LabeledPolynomial.times(other: C): LabeledPolynomial = - LabeledPolynomial( - coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this[degs]!! * other - } - ) - - /** - * Converts the constant [value] to polynomial. - */ - public override fun number(value: C): LabeledPolynomial = - LabeledPolynomial(mapOf(emptyMap() to value)) - - public override operator fun Symbol.unaryPlus(): LabeledPolynomial = - LabeledPolynomial(mapOf( - mapOf(this to 1U) to constantOne, - )) - public override operator fun Symbol.unaryMinus(): LabeledPolynomial = - LabeledPolynomial(mapOf( - mapOf(this to 1U) to -constantOne, - )) - public override operator fun Symbol.plus(other: Symbol): LabeledPolynomial = - if (this == other) LabeledPolynomial(mapOf( - mapOf(this to 1U) to constantOne * 2 - )) - else LabeledPolynomial(mapOf( - mapOf(this to 1U) to constantOne, - mapOf(other to 1U) to constantOne, - )) - public override operator fun Symbol.minus(other: Symbol): LabeledPolynomial = - if (this == other) zero - else LabeledPolynomial(mapOf( - mapOf(this to 1U) to constantOne, - mapOf(other to 1U) to -constantOne, - )) - public override operator fun Symbol.times(other: Symbol): LabeledPolynomial = - if (this == other) LabeledPolynomial(mapOf( - mapOf(this to 2U) to constantOne - )) - else LabeledPolynomial(mapOf( - mapOf(this to 1U, other to 1U) to constantOne, - )) - - public override operator fun Symbol.plus(other: LabeledPolynomial): LabeledPolynomial = - with(other.coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(mapOf(this@plus to 1u) to constantOne)) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = mapOf(this@plus to 1U) - - this[degs] = constantOne + getOrElse(degs) { constantZero } - } - ) - } - public override operator fun Symbol.minus(other: LabeledPolynomial): LabeledPolynomial = - with(other.coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(mapOf(this@minus to 1u) to constantOne)) - else LabeledPolynomial( - toMutableMap() - .apply { - forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } - - val degs = mapOf(this@minus to 1U) - - this[degs] = constantOne - getOrElse(degs) { constantZero } - } - ) - } - public override operator fun Symbol.times(other: LabeledPolynomial): LabeledPolynomial = - LabeledPolynomial( - other.coefficients - .mapKeys { (degs, _) -> degs.toMutableMap().also{ it[this] = if (this in it) it[this]!! + 1U else 1U } } - ) - - public override operator fun LabeledPolynomial.plus(other: Symbol): LabeledPolynomial = - with(coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(mapOf(other to 1u) to constantOne)) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = mapOf(other to 1U) - - this[degs] = constantOne + getOrElse(degs) { constantZero } - } - ) - } - public override operator fun LabeledPolynomial.minus(other: Symbol): LabeledPolynomial = - with(coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(mapOf(other to 1u) to constantOne)) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = mapOf(other to 1U) - - this[degs] = constantOne - getOrElse(degs) { constantZero } - } - ) - } - public override operator fun LabeledPolynomial.times(other: Symbol): LabeledPolynomial = - LabeledPolynomial( - coefficients - .mapKeys { (degs, _) -> degs.toMutableMap().also{ it[other] = if (other in it) it[other]!! + 1U else 1U } } - ) - - /** - * Returns negation of the polynomial. - */ - override fun LabeledPolynomial.unaryMinus(): LabeledPolynomial = - LabeledPolynomial( - coefficients.mapValues { -it.value } - ) - /** - * Returns sum of the polynomials. - */ - override operator fun LabeledPolynomial.plus(other: LabeledPolynomial): LabeledPolynomial = - LabeledPolynomial( - buildMap(coefficients.size + other.coefficients.size) { - other.coefficients.mapValuesTo(this) { it.value } - other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value } - } - ) - /** - * Returns difference of the polynomials. - */ - override operator fun LabeledPolynomial.minus(other: LabeledPolynomial): LabeledPolynomial = - LabeledPolynomial( - buildMap(coefficients.size + other.coefficients.size) { - other.coefficients.mapValuesTo(this) { it.value } - other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value } - } - ) - /** - * Returns product of the polynomials. - */ - override operator fun LabeledPolynomial.times(other: LabeledPolynomial): LabeledPolynomial = - LabeledPolynomial( - buildMap(coefficients.size * other.coefficients.size) { - for ((degs1, c1) in coefficients) for ((degs2, c2) in other.coefficients) { - val degs = degs1.toMutableMap() - degs2.mapValuesTo(degs) { (variable, deg) -> degs.getOrElse(variable) { 0u } + deg } - val c = c1 * c2 - this[degs] = if (degs in this) this[degs]!! + c else c - } - } - ) - - /** - * Instance of zero polynomial (zero of the polynomial ring). - */ - override val zero: LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to constantZero)) - /** - * Instance of unit polynomial (unit of the polynomial ring). - */ - override val one: LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to constantOne)) - - /** - * 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, c) -> 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.entries.forEach { (degs, _) -> - degs.mapValuesTo(this) { (variable, deg) -> - max(getOrElse(variable) { 0u }, deg) - } - } - } - /** - * 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 - -// @Suppress("NOTHING_TO_INLINE") -// public inline fun LabeledPolynomial.substitute(argument: Map): LabeledPolynomial = this.substitute(ring, argument) -// @Suppress("NOTHING_TO_INLINE") -// @JvmName("substitutePolynomial") -// public inline fun LabeledPolynomial.substitute(argument: Map>): LabeledPolynomial = this.substitute(ring, argument) -// -// @Suppress("NOTHING_TO_INLINE") -// public inline fun LabeledPolynomial.asFunction(): (Map) -> LabeledPolynomial = { this.substitute(ring, it) } -// @Suppress("NOTHING_TO_INLINE") -// public inline fun LabeledPolynomial.asFunctionOnConstants(): (Map) -> LabeledPolynomial = { this.substitute(ring, it) } -// @Suppress("NOTHING_TO_INLINE") -// public inline fun LabeledPolynomial.asFunctionOnPolynomials(): (Map>) -> LabeledPolynomial = { this.substitute(ring, it) } -// -// @Suppress("NOTHING_TO_INLINE") -// public inline operator fun LabeledPolynomial.invoke(argument: Map): LabeledPolynomial = this.substitute(ring, argument) -// @Suppress("NOTHING_TO_INLINE") -// @JvmName("invokePolynomial") -// public inline operator fun LabeledPolynomial.invoke(argument: Map>): LabeledPolynomial = this.substitute(ring, argument) -} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt deleted file mode 100644 index 76c6874f5..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.invoke - - -public class LabeledRationalFunction( - public override val numerator: LabeledPolynomial, - public override val denominator: LabeledPolynomial -) : RationalFunction> { - override fun toString(): String = "LabeledRationalFunction${numerator.coefficients}/${denominator.coefficients}" -} - -public class LabeledRationalFunctionSpace>( - public val ring: A, -) : - MultivariateRationalFunctionalSpaceOverMultivariatePolynomialSpace< - C, - Symbol, - LabeledPolynomial, - LabeledRationalFunction, - LabeledPolynomialSpace, - >, - MultivariatePolynomialSpaceOfFractions< - C, - Symbol, - LabeledPolynomial, - LabeledRationalFunction, - >() { - - override val polynomialRing : LabeledPolynomialSpace = LabeledPolynomialSpace(ring) - override fun constructRationalFunction( - numerator: LabeledPolynomial, - denominator: LabeledPolynomial - ): LabeledRationalFunction = - LabeledRationalFunction(numerator, denominator) - - /** - * Instance of zero rational function (zero of the rational functions ring). - */ - public override val zero: LabeledRationalFunction = LabeledRationalFunction(polynomialZero, polynomialOne) - /** - * Instance of unit polynomial (unit of the rational functions ring). - */ - public override val one: LabeledRationalFunction = LabeledRationalFunction(polynomialOne, polynomialOne) - - // TODO: Разобрать - -// operator fun invoke(arg: Map): LabeledRationalFunction = -// LabeledRationalFunction( -// numerator(arg), -// denominator(arg) -// ) -// -// @JvmName("invokeLabeledPolynomial") -// operator fun invoke(arg: Map>): LabeledRationalFunction = -// LabeledRationalFunction( -// numerator(arg), -// denominator(arg) -// ) -// -// @JvmName("invokeLabeledRationalFunction") -// operator fun invoke(arg: Map>): LabeledRationalFunction { -// var num = numerator invokeRFTakeNumerator arg -// var den = denominator invokeRFTakeNumerator arg -// for (variable in variables) if (variable in arg) { -// val degreeDif = degrees[variable]!! -// if (degreeDif > 0) -// den = multiplyByPower(den, arg[variable]!!.denominator, degreeDif) -// else -// num = multiplyByPower(num, arg[variable]!!.denominator, -degreeDif) -// } -// return LabeledRationalFunction(num, den) -// } -// -// override fun toString(): String = toString(emptyMap()) -// -// fun toString(names: Map = emptyMap()): String = -// when (true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toString(names) -// else -> "${numerator.toStringWithBrackets(names)}/${denominator.toStringWithBrackets(names)}" -// } -// -// fun toString(namer: (Symbol) -> String): String = -// when (true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toString(namer) -// else -> "${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)}" -// } -// -// fun toStringWithBrackets(names: Map = emptyMap()): String = -// when (true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toStringWithBrackets(names) -// else -> "(${numerator.toStringWithBrackets(names)}/${denominator.toStringWithBrackets(names)})" -// } -// -// fun toStringWithBrackets(namer: (Symbol) -> String): String = -// when (true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toStringWithBrackets(namer) -// else -> "(${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)})" -// } -// -// fun toReversedString(names: Map = emptyMap()): String = -// when (true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedString(names) -// else -> "${numerator.toReversedStringWithBrackets(names)}/${denominator.toReversedStringWithBrackets(names)}" -// } -// -// fun toReversedString(namer: (Symbol) -> String): String = -// when (true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedString(namer) -// else -> "${numerator.toReversedStringWithBrackets(namer)}/${denominator.toReversedStringWithBrackets(namer)}" -// } -// -// fun toReversedStringWithBrackets(names: Map = emptyMap()): String = -// when (true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedStringWithBrackets(names) -// else -> "(${numerator.toReversedStringWithBrackets(names)}/${denominator.toReversedStringWithBrackets(names)})" -// } -// -// fun toReversedStringWithBrackets(namer: (Symbol) -> String): String = -// when (true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedStringWithBrackets(namer) -// else -> "(${numerator.toReversedStringWithBrackets(namer)}/${denominator.toReversedStringWithBrackets(namer)})" -// } -} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt deleted file mode 100644 index e75373819..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.operations.invoke -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.ScaleOperations -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract -import kotlin.experimental.ExperimentalTypeInference -import kotlin.jvm.JvmName -import kotlin.math.max - - -/** - * Polynomial model without fixation on specific context they are applied to. - * - * @param C the type of constants. - */ -public data class NumberedPolynomial -internal constructor( - /** - * Map that collects coefficients of the polynomial. Every monomial `a x_1^{d_1} ... x_n^{d_n}` is represented as - * pair "key-value" in the map, where value is coefficients `a` and - * key is list that associates index of every variable in the monomial with multiplicity of the variable occurring - * in the monomial. For example coefficients of polynomial `5 x_1^2 x_3^3 - 6 x_2` can be represented as - * ``` - * mapOf( - * listOf(2, 0, 3) to 5, - * listOf(0, 1) to (-6), - * ) - * ``` - * and also as - * ``` - * mapOf( - * listOf(2, 0, 3) to 5, - * listOf(0, 1) to (-6), - * listOf(0, 1, 1) to 0, - * ) - * ``` - * It is recommended not to put zero monomials into the map, but is not prohibited. Lists of degrees always do not - * contain any zeros on end, but can contain zeros on start or anywhere in middle. - */ - public val coefficients: Map, C> -) : Polynomial { - override fun toString(): String = "NumberedPolynomial$coefficients" -} - -/** - * Space of polynomials. - * - * @param C the type of operated polynomials. - * @param A the intersection of [Ring] of [C] and [ScaleOperations] of [C]. - * @param ring the [A] instance. - */ -public open class NumberedPolynomialSpace>( - public final override val ring: A, -) : PolynomialSpaceOverRing, A> { - /** - * Returns sum of the polynomial and the integer represented as 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 - NumberedPolynomial( - coefficients - .toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = getOrElse(degs) { constantZero } + other - } - ) - /** - * Returns difference between the polynomial and the integer represented as 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 - NumberedPolynomial( - coefficients - .toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = getOrElse(degs) { constantZero } - other - } - ) - /** - * Returns product of the polynomial and the integer represented as polynomial. - * - * The operation is equivalent to sum of [other] copies of [this]. - */ - public override operator fun NumberedPolynomial.times(other: Int): NumberedPolynomial = - if (other == 0) zero - else NumberedPolynomial( - coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this[degs]!! * other - } - ) - - /** - * Returns sum of the integer represented as 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 - NumberedPolynomial( - other.coefficients - .toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = this@plus + getOrElse(degs) { constantZero } - } - ) - /** - * Returns difference between the integer represented as 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 = - if (this == 0) other - else - NumberedPolynomial( - other.coefficients - .toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = this@minus - getOrElse(degs) { constantZero } - } - ) - /** - * Returns product of the integer represented as polynomial and the polynomial. - * - * The operation is equivalent to sum of [this] copies of [other]. - */ - public override operator fun Int.times(other: NumberedPolynomial): NumberedPolynomial = - if (this == 0) zero - else NumberedPolynomial( - other.coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this@times * this[degs]!! - } - ) - - /** - * Converts the integer [value] to polynomial. - */ - public override fun number(value: Int): NumberedPolynomial = number(constantNumber(value)) - - /** - * Returns sum of the constant represented as polynomial and the polynomial. - */ - override operator fun C.plus(other: NumberedPolynomial): NumberedPolynomial = - with(other.coefficients) { - if (isEmpty()) NumberedPolynomial(mapOf(emptyList() to this@plus)) - else NumberedPolynomial( - toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = this@plus + getOrElse(degs) { constantZero } - } - ) - } - /** - * Returns difference between the constant represented as polynomial and the polynomial. - */ - override operator fun C.minus(other: NumberedPolynomial): NumberedPolynomial = - with(other.coefficients) { - if (isEmpty()) NumberedPolynomial(mapOf(emptyList() to this@minus)) - else NumberedPolynomial( - toMutableMap() - .apply { - forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } - - val degs = emptyList() - - this[degs] = this@minus - getOrElse(degs) { constantZero } - } - ) - } - /** - * Returns product of the constant represented as polynomial and the polynomial. - */ - override operator fun C.times(other: NumberedPolynomial): NumberedPolynomial = - NumberedPolynomial( - other.coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this@times * this[degs]!! - } - ) - - /** - * Returns sum of the constant represented as polynomial and the polynomial. - */ - override operator fun NumberedPolynomial.plus(other: C): NumberedPolynomial = - with(coefficients) { - if (isEmpty()) NumberedPolynomial(mapOf(emptyList() to other)) - else NumberedPolynomial( - toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = getOrElse(degs) { constantZero } + other - } - ) - } - /** - * Returns difference between the constant represented as polynomial and the polynomial. - */ - override operator fun NumberedPolynomial.minus(other: C): NumberedPolynomial = - with(coefficients) { - if (isEmpty()) NumberedPolynomial(mapOf(emptyList() to other)) - else NumberedPolynomial( - toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = getOrElse(degs) { constantZero } - other - } - ) - } - /** - * Returns product of the constant represented as polynomial and the polynomial. - */ - override operator fun NumberedPolynomial.times(other: C): NumberedPolynomial = - NumberedPolynomial( - coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this[degs]!! * other - } - ) - - /** - * Converts the constant [value] to polynomial. - */ - public override fun number(value: C): NumberedPolynomial = - NumberedPolynomial(mapOf(emptyList() to value)) - - /** - * Returns negation of the polynomial. - */ - override fun NumberedPolynomial.unaryMinus(): NumberedPolynomial = - NumberedPolynomial( - coefficients.mapValues { -it.value } - ) - /** - * Returns sum of the polynomials. - */ - override operator fun NumberedPolynomial.plus(other: NumberedPolynomial): NumberedPolynomial = - NumberedPolynomial( - buildMap(coefficients.size + other.coefficients.size) { - other.coefficients.mapValuesTo(this) { it.value } - other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value } - } - ) - /** - * Returns difference of the polynomials. - */ - override operator fun NumberedPolynomial.minus(other: NumberedPolynomial): NumberedPolynomial = - NumberedPolynomial( - buildMap(coefficients.size + other.coefficients.size) { - other.coefficients.mapValuesTo(this) { it.value } - other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value } - } - ) - /** - * Returns product of the polynomials. - */ - override operator fun NumberedPolynomial.times(other: NumberedPolynomial): NumberedPolynomial = - NumberedPolynomial( - 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 - this[degs] = if (degs in this) this[degs]!! + c else c - } - } - ) - - /** - * Instance of zero polynomial (zero of the polynomial ring). - */ - override val zero: NumberedPolynomial = NumberedPolynomial(emptyMap()) - /** - * Instance of unit polynomial (unit of the polynomial ring). - */ - override val one: NumberedPolynomial = - NumberedPolynomial( - mapOf( - emptyList() to constantOne // 1 * x_1^0 * x_2^0 * ... - ) - ) - - /** - * 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.entries.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.entries.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.entries.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.entries.maxOfOrNull { (degs, _) -> degs.getOrElse(variable) { 0u } } ?: 0u - /** - * Counts degree of the polynomial by the specified [variables]. - */ - public fun NumberedPolynomial.degreeBy(variables: Collection): UInt = - coefficients.entries.maxOfOrNull { (degs, _) -> - degs.withIndex().filter { (index, _) -> index in variables }.sumOf { it.value } - } ?: 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 } - - @Suppress("NOTHING_TO_INLINE") - public inline fun NumberedPolynomial.substitute(argument: Map): NumberedPolynomial = this.substitute(ring, argument) - @Suppress("NOTHING_TO_INLINE") - @JvmName("substitutePolynomial") - public inline fun NumberedPolynomial.substitute(argument: Map>): NumberedPolynomial = this.substitute(ring, argument) - - @Suppress("NOTHING_TO_INLINE") - public inline fun NumberedPolynomial.asFunction(): (Map) -> NumberedPolynomial = { this.substitute(ring, it) } - @Suppress("NOTHING_TO_INLINE") - public inline fun NumberedPolynomial.asFunctionOnConstants(): (Map) -> NumberedPolynomial = { this.substitute(ring, it) } - @Suppress("NOTHING_TO_INLINE") - public inline fun NumberedPolynomial.asFunctionOnPolynomials(): (Map>) -> NumberedPolynomial = { this.substitute(ring, it) } - - @Suppress("NOTHING_TO_INLINE") - public inline operator fun NumberedPolynomial.invoke(argument: Map): NumberedPolynomial = this.substitute(ring, argument) - @Suppress("NOTHING_TO_INLINE") - @JvmName("invokePolynomial") - public inline operator fun NumberedPolynomial.invoke(argument: Map>): NumberedPolynomial = this.substitute(ring, argument) - - // FIXME: Move to other constructors with context receiver - public fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(emptyList() to this)) -} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt deleted file mode 100644 index 30c7f0188..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.invoke -import kotlin.math.max - - -public class NumberedRationalFunction internal constructor( - public override val numerator: NumberedPolynomial, - public override val denominator: NumberedPolynomial -) : RationalFunction> { - override fun toString(): String = "NumberedRationalFunction${numerator.coefficients}/${denominator.coefficients}" -} - -public class NumberedRationalFunctionSpace> ( - public val ring: A, -) : - RationalFunctionalSpaceOverPolynomialSpace< - C, - NumberedPolynomial, - NumberedRationalFunction, - NumberedPolynomialSpace, - >, - PolynomialSpaceOfFractions< - C, - NumberedPolynomial, - NumberedRationalFunction, - >() { - - override val polynomialRing : NumberedPolynomialSpace = NumberedPolynomialSpace(ring) - override fun constructRationalFunction( - numerator: NumberedPolynomial, - denominator: NumberedPolynomial - ): NumberedRationalFunction = - NumberedRationalFunction(numerator, denominator) - - /** - * Instance of zero rational function (zero of the rational functions ring). - */ - public override val zero: NumberedRationalFunction = NumberedRationalFunction(polynomialZero, polynomialOne) - /** - * Instance of unit polynomial (unit of the rational functions ring). - */ - public override val one: NumberedRationalFunction = NumberedRationalFunction(polynomialOne, polynomialOne) - - /** - * 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: Разобрать - -// operator fun invoke(arg: Map): NumberedRationalFunction = -// NumberedRationalFunction( -// numerator(arg), -// denominator(arg) -// ) -// -// @JvmName("invokePolynomial") -// operator fun invoke(arg: Map>): NumberedRationalFunction = -// NumberedRationalFunction( -// numerator(arg), -// denominator(arg) -// ) -// -// @JvmName("invokeRationalFunction") -// operator fun invoke(arg: Map>): NumberedRationalFunction { -// var num = numerator invokeRFTakeNumerator arg -// var den = denominator invokeRFTakeNumerator arg -// for (variable in 0 until max(numerator.countOfVariables, denominator.countOfVariables)) if (variable in arg) { -// val degreeDif = numerator.degrees.getOrElse(variable) { 0 } - denominator.degrees.getOrElse(variable) { 0 } -// if (degreeDif > 0) -// den = multiplyByPower(den, arg[variable]!!.denominator, degreeDif) -// else -// num = multiplyByPower(num, arg[variable]!!.denominator, -degreeDif) -// } -// return NumberedRationalFunction(num, den) -// } -// -// override fun toString(): String = toString(Polynomial.variableName) -// -// fun toString(withVariableName: String = Polynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toString(withVariableName) -// else -> "${numerator.toStringWithBrackets(withVariableName)}/${denominator.toStringWithBrackets(withVariableName)}" -// } -// -// fun toString(namer: (Int) -> String): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toString(namer) -// else -> "${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)}" -// } -// -// fun toStringWithBrackets(withVariableName: String = Polynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toStringWithBrackets(withVariableName) -// else -> "(${numerator.toStringWithBrackets(withVariableName)}/${denominator.toStringWithBrackets(withVariableName)})" -// } -// -// fun toStringWithBrackets(namer: (Int) -> String): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toStringWithBrackets(namer) -// else -> "(${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)})" -// } -// -// fun toReversedString(withVariableName: String = Polynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedString(withVariableName) -// else -> "${numerator.toReversedStringWithBrackets(withVariableName)}/${denominator.toReversedStringWithBrackets(withVariableName)}" -// } -// -// fun toReversedString(namer: (Int) -> String): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedString(namer) -// else -> "${numerator.toReversedStringWithBrackets(namer)}/${denominator.toReversedStringWithBrackets(namer)}" -// } -// -// fun toReversedStringWithBrackets(withVariableName: String = Polynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedStringWithBrackets(withVariableName) -// else -> "(${numerator.toReversedStringWithBrackets(withVariableName)}/${denominator.toReversedStringWithBrackets(withVariableName)})" -// } -// -// fun toReversedStringWithBrackets(namer: (Int) -> String): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedStringWithBrackets(namer) -// else -> "(${numerator.toReversedStringWithBrackets(namer)}/${denominator.toReversedStringWithBrackets(namer)})" -// } -} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt deleted file mode 100644 index 612b00535..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.operations.Ring - -/** - * Represents piecewise-defined function. - * - * @param T the piece key type. - * @param R the sub-function type. - */ -public fun interface Piecewise { - /** - * Returns the appropriate sub-function for given piece key. - */ - public fun findPiece(arg: T): R? -} - -/** - * Represents piecewise-defined function where all the sub-functions are polynomials. - * - * @property pieces An ordered list of range-polynomial pairs. The list does not in general guarantee that there are no - * "holes" in it. - */ -public interface PiecewisePolynomial> : Piecewise> { - public val pieces: Collection, ListPolynomial>> - - override fun findPiece(arg: T): ListPolynomial? -} - -/** - * A generic piecewise without constraints on how pieces are placed - */ -@PerformancePitfall("findPiece method of resulting piecewise is slow") -public fun > PiecewisePolynomial( - pieces: Collection, ListPolynomial>>, -): PiecewisePolynomial = object : PiecewisePolynomial { - override val pieces: Collection, ListPolynomial>> = pieces - - override fun findPiece(arg: T): ListPolynomial? = pieces.firstOrNull { arg in it.first }?.second -} - -/** - * An optimized piecewise that uses not separate pieces, but a range separated by delimiters. - * The pieces search is logarithmic. - */ -private class OrderedPiecewisePolynomial>( - override val pieces: List, ListPolynomial>>, -) : PiecewisePolynomial { - - override fun findPiece(arg: T): ListPolynomial? { - val index = pieces.binarySearch { (range, _) -> - when { - arg >= range.endInclusive -> -1 - arg < range.start -> +1 - else -> 0 - } - } - return if (index < 0) null else pieces[index].second - } - -} - -/** - * A [Piecewise] builder where all the pieces are ordered by the [Comparable] type instances. - * - * @param T the comparable piece key type. - * @param delimiter the initial piecewise separator - */ -public class PiecewiseBuilder>(delimiter: T) { - private val delimiters: MutableList = arrayListOf(delimiter) - private val pieces: MutableList> = arrayListOf() - - /** - * Dynamically adds a piece to the right side (beyond maximum argument value of previous piece) - * - * @param right new rightmost position. If is less than current rightmost position, an error is thrown. - * @param piece the sub-function. - */ - public fun putRight(right: T, piece: ListPolynomial) { - require(right > delimiters.last()) { "New delimiter should be to the right of old one" } - delimiters += right - pieces += piece - } - - /** - * Dynamically adds a piece to the left side (beyond maximum argument value of previous piece) - * - * @param left the new leftmost position. If is less than current rightmost position, an error is thrown. - * @param piece the sub-function. - */ - public fun putLeft(left: T, piece: ListPolynomial) { - require(left < delimiters.first()) { "New delimiter should be to the left of old one" } - delimiters.add(0, left) - pieces.add(0, piece) - } - - public fun build(): PiecewisePolynomial = OrderedPiecewisePolynomial(delimiters.zipWithNext { l, r -> - l..r - }.zip(pieces)) -} - -/** - * A builder for [PiecewisePolynomial] - */ -public fun > PiecewisePolynomial( - startingPoint: T, - builder: PiecewiseBuilder.() -> Unit, -): PiecewisePolynomial = PiecewiseBuilder(startingPoint).apply(builder).build() - -/** - * Return a value of polynomial function with given [ring] a given [arg] or null if argument is outside piecewise - * definition. - */ -public fun , C : Ring> PiecewisePolynomial.substitute(ring: C, arg: T): T? = - findPiece(arg)?.substitute(ring, arg) - -/** - * Convert this polynomial to a function returning nullable value (null if argument is outside piecewise range). - */ -public fun , C : Ring> PiecewisePolynomial.asFunction(ring: C): (T) -> T? = { substitute(ring, it) } - -/** - * Convert this polynomial to a function using [defaultValue] for arguments outside the piecewise range. - */ -public fun , C : Ring> PiecewisePolynomial.asFunction(ring: C, defaultValue: T): (T) -> T = - { substitute(ring, it) ?: defaultValue } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt deleted file mode 100644 index e81a9388e..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.Ring - - -/** - * Returns the same degrees' description of the monomial, but without zero degrees. - */ -internal fun Map.cleanUp() = filterValues { it > 0U } - -// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(coefs, toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(coefs, toCheckInput) -@Suppress("FunctionName") -internal fun > A.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial { - if (!toCheckInput) return LabeledPolynomial(coefs) - - val fixedCoefs = LinkedHashMap, C>(coefs.size) - - for (entry in coefs) { - val key = entry.key.cleanUp() - val value = entry.value - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return LabeledPolynomial(fixedCoefs) -} - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs, toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs, toCheckInput) -@Suppress("FunctionName") -internal fun > A.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial { - if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) - - val fixedCoefs = LinkedHashMap, C>(pairs.size) - - for (entry in pairs) { - val key = entry.first.cleanUp() - val value = entry.second - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return LabeledPolynomial(fixedCoefs) -} - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs = pairs, toCheckInput = toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs = pairs, toCheckInput = toCheckInput) -@Suppress("FunctionName") -internal fun > A.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial { - if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) - - val fixedCoefs = LinkedHashMap, C>(pairs.size) - - for (entry in pairs) { - val key = entry.first.cleanUp() - val value = entry.second - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return LabeledPolynomial(fixedCoefs) -} - -@Suppress("FunctionName") -public fun > A.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledPolynomialSpace.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) - -@Suppress("FunctionName") -public fun > A.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledPolynomialSpace.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) - -@Suppress("FunctionName") -public fun > A.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledPolynomialSpace.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) - -//context(A) -//public fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to one)) -//context(LabeledPolynomialSpace) -//public fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to constantOne)) -//context(LabeledRationalFunctionSpace) -//public fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to constantOne)) - -public fun C.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to this)) - -@DslMarker -@UnstableKMathAPI -internal annotation class LabeledPolynomialConstructorDSL - -@UnstableKMathAPI -@LabeledPolynomialConstructorDSL -public class LabeledPolynomialTermSignatureBuilder { - private val signature: MutableMap = LinkedHashMap() - public fun build(): Map = signature - public infix fun Symbol.inPowerOf(deg: UInt) { - signature[this] = deg - } - @Suppress("NOTHING_TO_INLINE") - public inline infix fun Symbol.pow(deg: UInt): Unit = this inPowerOf deg - @Suppress("NOTHING_TO_INLINE") - public inline infix fun Symbol.`in`(deg: UInt): Unit = this inPowerOf deg - @Suppress("NOTHING_TO_INLINE") - public inline infix fun Symbol.of(deg: UInt): Unit = this inPowerOf deg -} - -@UnstableKMathAPI -public class LabeledPolynomialBuilder(private val zero: C, private val add: (C, C) -> C, capacity: Int = 0) { - private val coefficients: MutableMap, C> = LinkedHashMap(capacity) - public fun build(): LabeledPolynomial = LabeledPolynomial(coefficients) - public operator fun C.invoke(block: LabeledPolynomialTermSignatureBuilder.() -> Unit) { - val signature = LabeledPolynomialTermSignatureBuilder().apply(block).build() - coefficients[signature] = add(coefficients.getOrElse(signature) { zero }, this@invoke) - } - @Suppress("NOTHING_TO_INLINE") - public inline infix fun C.with(noinline block: LabeledPolynomialTermSignatureBuilder.() -> Unit): Unit = this.invoke(block) - @Suppress("NOTHING_TO_INLINE") - public inline infix fun (LabeledPolynomialTermSignatureBuilder.() -> Unit).with(coef: C): Unit = coef.invoke(this) - @Suppress("NOTHING_TO_INLINE") - public infix fun sig(block: LabeledPolynomialTermSignatureBuilder.() -> Unit): LabeledPolynomialTermSignatureBuilder.() -> Unit = block -} - -// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available - -@UnstableKMathAPI -@LabeledPolynomialConstructorDSL -@Suppress("FunctionName") -public inline fun > A.LabeledPolynomial(block: LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = LabeledPolynomialBuilder(zero, ::add).apply(block).build() -@UnstableKMathAPI -@LabeledPolynomialConstructorDSL -@Suppress("FunctionName") -public inline fun > A.LabeledPolynomial(capacity: Int, block: LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = LabeledPolynomialBuilder(zero, ::add, capacity).apply(block).build() -@UnstableKMathAPI -@LabeledPolynomialConstructorDSL -@Suppress("FunctionName") -public inline fun > LabeledPolynomialSpace.LabeledPolynomial(block: LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = LabeledPolynomialBuilder(constantZero, { left: C, right: C -> left + right}).apply(block).build() -@UnstableKMathAPI -@LabeledPolynomialConstructorDSL -@Suppress("FunctionName") -public inline fun > LabeledPolynomialSpace.LabeledPolynomial(capacity: Int, block: LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = LabeledPolynomialBuilder(constantZero, { left: C, right: C -> left + right}, capacity).apply(block).build() - -// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available - -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): LabeledRationalFunction = - LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients, toCheckInput = true), - LabeledPolynomial(denominatorCoefficients, toCheckInput = true) - ) -@Suppress("FunctionName") -public fun > A.LabeledRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): LabeledRationalFunction = - LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients, toCheckInput = true), - LabeledPolynomial(denominatorCoefficients, toCheckInput = true) - ) -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numerator: LabeledPolynomial): LabeledRationalFunction = - LabeledRationalFunction(numerator, polynomialOne) -@Suppress("FunctionName") -public fun > A.LabeledRationalFunction(numerator: LabeledPolynomial): LabeledRationalFunction = - LabeledRationalFunction(numerator, LabeledPolynomial(mapOf(emptyMap() to one), toCheckInput = false)) -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numeratorCoefficients: Map, C>): LabeledRationalFunction = - LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients, toCheckInput = true), - polynomialOne - ) -@Suppress("FunctionName") -public fun > A.LabeledRationalFunction(numeratorCoefficients: Map, C>): LabeledRationalFunction = - LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients, toCheckInput = true), - LabeledPolynomial(mapOf(emptyMap() to one), toCheckInput = false) - ) - -//context(A) -//public fun > Symbol.asLabeledRationalFunction() : LabeledRationalFunction = LabeledRationalFunction(asLabeledPolynomial()) -//context(LabeledRationalFunctionSpace) -//public fun > Symbol.asLabeledRationalFunction() : LabeledRationalFunction = LabeledRationalFunction(asLabeledPolynomial()) - -//context(A) -//public fun > C.asLabeledRationalFunction() : LabeledRationalFunction = LabeledRationalFunction(asLabeledPolynomial()) -//context(LabeledRationalFunctionSpace) -//public fun > C.asLabeledRationalFunction() : LabeledRationalFunction = LabeledRationalFunction(asLabeledPolynomial()) \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt deleted file mode 100644 index af918b9ae..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt +++ /dev/null @@ -1,495 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.Field -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.invoke -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract - - -// TODO: Docs - -/** - * Creates a [LabeledPolynomialSpace] over a received ring. - */ -public fun > A.labeledPolynomial(): LabeledPolynomialSpace = - LabeledPolynomialSpace(this) - -/** - * Creates a [LabeledPolynomialSpace]'s scope over a received ring. - */ -@OptIn(ExperimentalContracts::class) -public inline fun , R> A.labeledPolynomial(block: LabeledPolynomialSpace.() -> R): R { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return LabeledPolynomialSpace(this).block() -} - -///** -// * Represents the polynomial as a [String] with names of variables substituted with names from [names]. -// * Consider that monomials are sorted in lexicographic order. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.represent(names: Map = emptyMap()): String = -// coefficients.entries -// .sortedWith { o1, o2 -> LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } -// .asSequence() -// .map { (degs, t) -> -// if (degs.isEmpty()) "$t" -// else { -// when { -// t.isOne() -> "" -// t.isMinusOne() -> "-" -// else -> "$t " -// } + -// degs -// .toSortedMap() -// .filter { it.value > 0U } -// .map { (variable, deg) -> -// val variableName = names.getOrDefault(variable, variable.toString()) -// when (deg) { -// 1U -> variableName -// else -> "$variableName^$deg" -// } -// } -// .joinToString(separator = " ") { it } -// } -// } -// .joinToString(separator = " + ") { it } -// .ifEmpty { "0" } -// -///** -// * Represents the polynomial as a [String] naming variables by [namer]. -// * Consider that monomials are sorted in lexicographic order. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.represent(namer: (Symbol) -> String): String = -// coefficients.entries -// .sortedWith { o1, o2 -> LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } -// .asSequence() -// .map { (degs, t) -> -// if (degs.isEmpty()) "$t" -// else { -// when { -// t.isOne() -> "" -// t.isMinusOne() -> "-" -// else -> "$t " -// } + -// degs -// .toSortedMap() -// .filter { it.value > 0U } -// .map { (variable, deg) -> -// when (deg) { -// 1U -> namer(variable) -// else -> "${namer(variable)}^$deg" -// } -// } -// .joinToString(separator = " ") { it } -// } -// } -// .joinToString(separator = " + ") { it } -// .ifEmpty { "0" } -// -///** -// * Represents the polynomial as a [String] with names of variables substituted with names from [names] and with -// * brackets around the string if needed (i.e. when there are at least two addends in the representation). -// * Consider that monomials are sorted in lexicographic order. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.representWithBrackets(names: Map = emptyMap()): String = -// with(represent(names)) { if (coefficients.count() == 1) this else "($this)" } -// -///** -// * Represents the polynomial as a [String] naming variables by [namer] and with brackets around the string if needed -// * (i.e. when there are at least two addends in the representation). -// * Consider that monomials are sorted in lexicographic order. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.representWithBrackets(namer: (Symbol) -> String): String = -// with(represent(namer)) { if (coefficients.count() == 1) this else "($this)" } -// -///** -// * Represents the polynomial as a [String] with names of variables substituted with names from [names]. -// * Consider that monomials are sorted in **reversed** lexicographic order. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.representReversed(names: Map = emptyMap()): String = -// coefficients.entries -// .sortedWith { o1, o2 -> -LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } -// .asSequence() -// .map { (degs, t) -> -// if (degs.isEmpty()) "$t" -// else { -// when { -// t.isOne() -> "" -// t.isMinusOne() -> "-" -// else -> "$t " -// } + -// degs -// .toSortedMap() -// .filter { it.value > 0U } -// .map { (variable, deg) -> -// val variableName = names.getOrDefault(variable, variable.toString()) -// when (deg) { -// 1U -> variableName -// else -> "$variableName^$deg" -// } -// } -// .joinToString(separator = " ") { it } -// } -// } -// .joinToString(separator = " + ") { it } -// .ifEmpty { "0" } -// -///** -// * Represents the polynomial as a [String] naming variables by [namer]. -// * Consider that monomials are sorted in **reversed** lexicographic order. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.representReversed(namer: (Symbol) -> String): String = -// coefficients.entries -// .sortedWith { o1, o2 -> -LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } -// .asSequence() -// .map { (degs, t) -> -// if (degs.isEmpty()) "$t" -// else { -// when { -// t.isOne() -> "" -// t.isMinusOne() -> "-" -// else -> "$t " -// } + -// degs -// .toSortedMap() -// .filter { it.value > 0U } -// .map { (variable, deg) -> -// when (deg) { -// 1U -> namer(variable) -// else -> "${namer(variable)}^$deg" -// } -// } -// .joinToString(separator = " ") { it } -// } -// } -// .joinToString(separator = " + ") { it } -// .ifEmpty { "0" } -// -///** -// * Represents the polynomial as a [String] with names of variables substituted with names from [names] and with -// * brackets around the string if needed (i.e. when there are at least two addends in the representation). -// * Consider that monomials are sorted in **reversed** lexicographic order. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.representReversedWithBrackets(names: Map = emptyMap()): String = -// with(representReversed(names)) { if (coefficients.count() == 1) this else "($this)" } -// -///** -// * Represents the polynomial as a [String] naming variables by [namer] and with brackets around the string if needed -// * (i.e. when there are at least two addends in the representation). -// * Consider that monomials are sorted in **reversed** lexicographic order. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.representReversedWithBrackets(namer: (Symbol) -> String): String = -// with(representReversed(namer)) { if (coefficients.count() == 1) this else "($this)" } - -//operator fun > Polynomial.div(other: T): Polynomial = -// if (other.isZero()) throw ArithmeticException("/ by zero") -// else -// Polynomial( -// coefficients -// .mapValues { it.value / other }, -// toCheckInput = false -// ) - -//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 = degs.entries.asSequence().filter { it.key in args }.fold(c) { acc, (variable, deg) -> -// multiplyWithPower(acc, args[variable]!!, deg) -// } -// this[newDegs] = if (newDegs in this) this[newDegs]!! + newC else newC -// } -// } -// ) -//} -// -//// TODO: Replace with optimisation: the [result] may be unboxed, and all operations may be performed as soon as -//// possible on it -//@JvmName("substitutePolynomial") -//fun LabeledPolynomial.substitute(ring: Ring, arg: Map>) : LabeledPolynomial = -// ring.labeledPolynomial { -// if (coefficients.isEmpty()) return zero -// coefficients -// .asSequence() -// .map { (degs, c) -> -// degs.entries -// .asSequence() -// .filter { it.key in arg } -// .fold(LabeledPolynomial(mapOf(degs.filterKeys { it !in arg } to c))) { acc, (index, deg) -> -// multiplyWithPower(acc, arg[index]!!, deg) -// } -// } -// .reduce { acc, polynomial -> acc + polynomial } // TODO: Rewrite. Might be slow. -// } -// -//// TODO: Substitute rational function -// -//fun > LabeledPolynomial.asFunctionOver(ring: A): (Map) -> LabeledPolynomial = -// { substitute(ring, it) } -// -//fun > LabeledPolynomial.asPolynomialFunctionOver(ring: A): (Map>) -> LabeledPolynomial = -// { substitute(ring, it) } - -/** - * Returns algebraic derivative of received polynomial. - */ -@UnstableKMathAPI -public fun > LabeledPolynomial.derivativeWithRespectTo( - algebra: A, - variable: Symbol, -): LabeledPolynomial = algebra { - LabeledPolynomial( - buildMap(coefficients.size) { - 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. - */ -@UnstableKMathAPI -public fun > LabeledPolynomial.derivativeWithRespectTo( - algebra: A, - variables: Collection, -): LabeledPolynomial = algebra { - val cleanedVariables = variables.toSet() - if (cleanedVariables.isEmpty()) return this@derivativeWithRespectTo - LabeledPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - if (!degs.keys.containsAll(cleanedVariables)) return@forEach - put( - buildMap { - degs.forEach { (vari, deg) -> - when { - vari !in cleanedVariables -> put(vari, deg) - deg > 1u -> put(vari, deg - 1u) - } - } - }, - cleanedVariables.fold(c) { acc, variable -> multiplyByDoubling(acc, degs[variable]!!) } - ) - } - } - ) -} - -/** - * Returns algebraic derivative of received polynomial. - */ -@UnstableKMathAPI -public fun > LabeledPolynomial.nthDerivativeWithRespectTo( - algebra: A, - variable: Symbol, - order: UInt -): LabeledPolynomial = algebra { - if (order == 0u) return this@nthDerivativeWithRespectTo - LabeledPolynomial( - buildMap(coefficients.size) { - 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. - */ -@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.size) { - 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. - */ -@UnstableKMathAPI -public fun > LabeledPolynomial.antiderivativeWithRespectTo( - algebra: A, - variable: Symbol, -): LabeledPolynomial = algebra { - LabeledPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - val newDegs = buildMap(degs.size + 1) { - put(variable, 1u) - for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) - } - put( - newDegs, - c / multiplyByDoubling(one, newDegs[variable]!!) - ) - } - } - ) -} - -/** - * Returns algebraic antiderivative of received polynomial. - */ -@UnstableKMathAPI -public fun > LabeledPolynomial.antiderivativeWithRespectTo( - algebra: A, - variables: Collection, -): LabeledPolynomial = algebra { - val cleanedVariables = variables.toSet() - if (cleanedVariables.isEmpty()) return this@antiderivativeWithRespectTo - LabeledPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - val newDegs = buildMap(degs.size + 1) { - for (variable in cleanedVariables) put(variable, 1u) - for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) - } - put( - newDegs, - cleanedVariables.fold(c) { acc, variable -> acc / multiplyByDoubling(one, newDegs[variable]!!) } - ) - } - } - ) -} - -/** - * Returns algebraic derivative of received polynomial. - */ -@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 = buildMap(degs.size + 1) { - put(variable, order) - for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) - } - 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. - */ -@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 = buildMap(degs.size + 1) { - for ((variable, order) in filteredVariablesAndOrders) put(variable, order) - for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) - } - 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-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt deleted file mode 100644 index 583160cf4..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.operations.Ring -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract - - -/** - * Creates a [LabeledRationalFunctionSpace] over a received ring. - */ -public fun > A.labeledRationalFunction(): LabeledRationalFunctionSpace = - LabeledRationalFunctionSpace(this) - -/** - * Creates a [LabeledRationalFunctionSpace]'s scope over a received ring. - */ -public inline fun , R> A.labeledRationalFunction(block: LabeledRationalFunctionSpace.() -> R): R { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return LabeledRationalFunctionSpace(this).block() -} - -//fun > LabeledRationalFunction.reduced(): LabeledRationalFunction { -// val greatestCommonDivider = polynomialGCD(numerator, denominator) -// return LabeledRationalFunction( -// numerator / greatestCommonDivider, -// denominator / greatestCommonDivider -// ) -//} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt deleted file mode 100644 index dca8a0cff..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.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) - -// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(coefs, toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(coefs, toCheckInput) -@Suppress("FunctionName") -internal fun > A.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial { - if (!toCheckInput) return NumberedPolynomial(coefs) - - val fixedCoefs = mutableMapOf, C>() - - for (entry in coefs) { - val key = entry.key.cleanUp() - val value = entry.value - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return NumberedPolynomial(fixedCoefs) -} - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs, toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs, toCheckInput) -@Suppress("FunctionName") -internal fun > A.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial { - if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) - - val fixedCoefs = mutableMapOf, C>() - - for (entry in pairs) { - val key = entry.first.cleanUp() - val value = entry.second - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return NumberedPolynomial(fixedCoefs) -} - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs = pairs, toCheckInput = toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs = pairs, toCheckInput = toCheckInput) -@Suppress("FunctionName") -internal fun > A.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial { - if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) - - val fixedCoefs = mutableMapOf, C>() - - for (entry in pairs) { - val key = entry.first.cleanUp() - val value = entry.second - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return NumberedPolynomial(fixedCoefs) -} - -@Suppress("FunctionName") -public fun > A.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedPolynomialSpace.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) - -@Suppress("FunctionName") -public fun > A.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedPolynomialSpace.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) - -@Suppress("FunctionName") -public fun > A.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedPolynomialSpace.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) - -public fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(emptyList() to this)) - -@DslMarker -@UnstableKMathAPI -internal annotation class NumberedPolynomialConstructorDSL - -@UnstableKMathAPI -@NumberedPolynomialConstructorDSL -public class NumberedPolynomialTermSignatureBuilder { - private val signature: MutableList = ArrayList() - public fun build(): List = signature - public infix fun Int.inPowerOf(deg: UInt) { - if (this > signature.lastIndex) { - signature.addAll(List(this - signature.lastIndex - 1) { 0u }) - signature.add(deg) - } else { - signature[this] = deg - } - } - @Suppress("NOTHING_TO_INLINE") - public inline infix fun Int.pow(deg: UInt): Unit = this inPowerOf deg - @Suppress("NOTHING_TO_INLINE") - public inline infix fun Int.`in`(deg: UInt): Unit = this inPowerOf deg - @Suppress("NOTHING_TO_INLINE") - public inline infix fun Int.of(deg: UInt): Unit = this inPowerOf deg -} - -@UnstableKMathAPI -public class NumberedPolynomialBuilder(private val zero: C, private val add: (C, C) -> C, capacity: Int = 0) { - private val coefficients: MutableMap, C> = LinkedHashMap(capacity) - public fun build(): NumberedPolynomial = NumberedPolynomial(coefficients) - public operator fun C.invoke(block: NumberedPolynomialTermSignatureBuilder.() -> Unit) { - val signature = NumberedPolynomialTermSignatureBuilder().apply(block).build() - coefficients[signature] = add(coefficients.getOrElse(signature) { zero }, this@invoke) - } - @Suppress("NOTHING_TO_INLINE") - public inline infix fun C.with(noinline block: NumberedPolynomialTermSignatureBuilder.() -> Unit): Unit = this.invoke(block) - @Suppress("NOTHING_TO_INLINE") - public inline infix fun (NumberedPolynomialTermSignatureBuilder.() -> Unit).with(coef: C): Unit = coef.invoke(this) - @Suppress("NOTHING_TO_INLINE") - public infix fun sig(block: NumberedPolynomialTermSignatureBuilder.() -> Unit): NumberedPolynomialTermSignatureBuilder.() -> Unit = block -} - -// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available - -@UnstableKMathAPI -@NumberedPolynomialConstructorDSL -@Suppress("FunctionName") -public inline fun > A.NumberedPolynomial(block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder(zero, ::add).apply(block).build() -@UnstableKMathAPI -@NumberedPolynomialConstructorDSL -@Suppress("FunctionName") -public inline fun > A.NumberedPolynomial(capacity: Int, block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder(zero, ::add, capacity).apply(block).build() -@UnstableKMathAPI -@NumberedPolynomialConstructorDSL -@Suppress("FunctionName") -public inline fun > NumberedPolynomialSpace.NumberedPolynomial(block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder(constantZero, { left: C, right: C -> left + right}).apply(block).build() -@UnstableKMathAPI -@NumberedPolynomialConstructorDSL -@Suppress("FunctionName") -public inline fun > NumberedPolynomialSpace.NumberedPolynomial(capacity: Int, block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder(constantZero, { left: C, right: C -> left + right}, capacity).apply(block).build() - -// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available - -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): NumberedRationalFunction = - NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients, toCheckInput = true), - NumberedPolynomial(denominatorCoefficients, toCheckInput = true) - ) -@Suppress("FunctionName") -public fun > A.NumberedRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): NumberedRationalFunction = - NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients, toCheckInput = true), - NumberedPolynomial(denominatorCoefficients, toCheckInput = true) - ) -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numerator: NumberedPolynomial): NumberedRationalFunction = - NumberedRationalFunction(numerator, polynomialOne) -@Suppress("FunctionName") -public fun > A.NumberedRationalFunction(numerator: NumberedPolynomial): NumberedRationalFunction = - NumberedRationalFunction(numerator, NumberedPolynomial(mapOf(emptyList() to one), toCheckInput = false)) -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numeratorCoefficients: Map, C>): NumberedRationalFunction = - NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients, toCheckInput = true), - polynomialOne - ) -@Suppress("FunctionName") -public fun > A.NumberedRationalFunction(numeratorCoefficients: Map, C>): NumberedRationalFunction = - NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients, toCheckInput = true), - NumberedPolynomial(mapOf(emptyList() to one), toCheckInput = false) - ) - -//context(A) -//public fun > C.asNumberedRationalFunction() : NumberedRationalFunction = NumberedRationalFunction(asLabeledPolynomial()) -//context(NumberedRationalFunctionSpace) -//public fun > C.asNumberedRationalFunction() : NumberedRationalFunction = NumberedRationalFunction(asLabeledPolynomial()) \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt deleted file mode 100644 index ad817c7ba..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt +++ /dev/null @@ -1,528 +0,0 @@ -package space.kscience.kmath.functions - -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.* -import kotlin.contracts.* -import kotlin.jvm.JvmName -import kotlin.math.max - - -// TODO: Docs - -/** - * Creates a [NumberedPolynomialSpace] over a received ring. - */ -public fun > A.numberedPolynomial(): NumberedPolynomialSpace = - NumberedPolynomialSpace(this) - -/** - * Creates a [NumberedPolynomialSpace]'s scope over a received ring. - */ -@OptIn(ExperimentalContracts::class) -public inline fun , R> A.numberedPolynomial(block: NumberedPolynomialSpace.() -> R): R { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return NumberedPolynomialSpace(this).block() -} - -///** -// * Represents the polynomial as a [String] where name of variable with index `i` is [withVariableName] + `"_${i+1}"`. -// * Consider that monomials are sorted in lexicographic order. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial.represent(withVariableName: String = NumberedPolynomial.defaultVariableName): String = -// coefficients.entries -// .sortedWith { o1, o2 -> NumberedPolynomial.monomialComparator.compare(o1.key, o2.key) } -// .asSequence() -// .map { (degs, t) -> -// if (degs.isEmpty()) "$t" -// else { -// when { -// t.isOne() -> "" -// t.isMinusOne() -> "-" -// else -> "$t " -// } + -// degs -// .mapIndexed { index, deg -> -// when (deg) { -// 0U -> "" -// 1U -> "${withVariableName}_${index+1}" -// else -> "${withVariableName}_${index+1}^$deg" -// } -// } -// .filter { it.isNotEmpty() } -// .joinToString(separator = " ") { it } -// } -// } -// .joinToString(separator = " + ") { it } -// .ifEmpty { "0" } -// -///** -// * Represents the polynomial as a [String] naming variables by [namer]. -// * Consider that monomials are sorted in lexicographic order. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial.represent(namer: (Int) -> String): String = -// coefficients.entries -// .sortedWith { o1, o2 -> NumberedPolynomial.monomialComparator.compare(o1.key, o2.key) } -// .asSequence() -// .map { (degs, t) -> -// if (degs.isEmpty()) "$t" -// else { -// when { -// t.isOne() -> "" -// t.isMinusOne() -> "-" -// else -> "$t " -// } + -// degs -// .mapIndexed { index, deg -> -// when (deg) { -// 0U -> "" -// 1U -> namer(index) -// else -> "${namer(index)}^$deg" -// } -// } -// .filter { it.isNotEmpty() } -// .joinToString(separator = " ") { it } -// } -// } -// .joinToString(separator = " + ") { it } -// .ifEmpty { "0" } -// -///** -// * Represents the polynomial as a [String] where name of variable with index `i` is [withVariableName] + `"_${i+1}"` -// * and with brackets around the string if needed (i.e. when there are at least two addends in the representation). -// * Consider that monomials are sorted in lexicographic order. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial.representWithBrackets(withVariableName: String = NumberedPolynomial.defaultVariableName): String = -// with(represent(withVariableName)) { if (coefficients.count() == 1) this else "($this)" } -// -///** -// * Represents the polynomial as a [String] naming variables by [namer] and with brackets around the string if needed -// * (i.e. when there are at least two addends in the representation). -// * Consider that monomials are sorted in lexicographic order. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial.representWithBrackets(namer: (Int) -> String): String = -// with(represent(namer)) { if (coefficients.count() == 1) this else "($this)" } -// -///** -// * Represents the polynomial as a [String] where name of variable with index `i` is [withVariableName] + `"_${i+1}"`. -// * Consider that monomials are sorted in **reversed** lexicographic order. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial.representReversed(withVariableName: String = NumberedPolynomial.defaultVariableName): String = -// coefficients.entries -// .sortedWith { o1, o2 -> -NumberedPolynomial.monomialComparator.compare(o1.key, o2.key) } -// .asSequence() -// .map { (degs, t) -> -// if (degs.isEmpty()) "$t" -// else { -// when { -// t.isOne() -> "" -// t.isMinusOne() -> "-" -// else -> "$t " -// } + -// degs -// .mapIndexed { index, deg -> -// when (deg) { -// 0U -> "" -// 1U -> "${withVariableName}_${index+1}" -// else -> "${withVariableName}_${index+1}^$deg" -// } -// } -// .filter { it.isNotEmpty() } -// .joinToString(separator = " ") { it } -// } -// } -// .joinToString(separator = " + ") { it } -// .ifEmpty { "0" } -// -///** -// * Represents the polynomial as a [String] naming variables by [namer]. -// * Consider that monomials are sorted in **reversed** lexicographic order. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial.representReversed(namer: (Int) -> String): String = -// coefficients.entries -// .sortedWith { o1, o2 -> -NumberedPolynomial.monomialComparator.compare(o1.key, o2.key) } -// .asSequence() -// .map { (degs, t) -> -// if (degs.isEmpty()) "$t" -// else { -// when { -// t.isOne() -> "" -// t.isMinusOne() -> "-" -// else -> "$t " -// } + -// degs -// .mapIndexed { index, deg -> -// when (deg) { -// 0U -> "" -// 1U -> namer(index) -// else -> "${namer(index)}^$deg" -// } -// } -// .filter { it.isNotEmpty() } -// .joinToString(separator = " ") { it } -// } -// } -// .joinToString(separator = " + ") { it } -// .ifEmpty { "0" } -// -///** -// * Represents the polynomial as a [String] where name of variable with index `i` is [withVariableName] + `"_${i+1}"` -// * and with brackets around the string if needed (i.e. when there are at least two addends in the representation). -// * Consider that monomials are sorted in **reversed** lexicographic order. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial.representReversedWithBrackets(withVariableName: String = NumberedPolynomial.defaultVariableName): String = -// with(representReversed(withVariableName)) { if (coefficients.count() == 1) this else "($this)" } -// -///** -// * Represents the polynomial as a [String] naming variables by [namer] and with brackets around the string if needed -// * (i.e. when there are at least two addends in the representation). -// * Consider that monomials are sorted in **reversed** lexicographic order. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial.representReversedWithBrackets(namer: (Int) -> String): String = -// with(representReversed(namer)) { if (coefficients.count() == 1) this else "($this)" } - -//public fun NumberedPolynomial.substitute(ring: Ring, args: Map): NumberedPolynomial = ring { -// if (coefficients.isEmpty()) return this@substitute -// NumberedPolynomial( -// buildMap { -// coefficients.forEach { (degs, c) -> -// val newDegs = degs.mapIndexed { index, deg -> if (index in args) 0U else deg }.cleanUp() -// val newC = degs.foldIndexed(c) { index, acc, deg -> -// if (index in args) multiplyWithPower(acc, args[index]!!, deg) -// else acc -// } -// this[newDegs] = if (newDegs in this) this[newDegs]!! + newC else newC -// } -// } -// ) -//} -// -//// TODO: Replace with optimisation: the [result] may be unboxed, and all operations may be performed as soon as -//// possible on it -//@JvmName("substitutePolynomial") -//public fun NumberedPolynomial.substitute(ring: Ring, arg: Map>) : NumberedPolynomial = -// ring.numberedPolynomialSpace { -// if (coefficients.isEmpty()) return zero -// coefficients -// .asSequence() -// .map { (degs, c) -> -// degs.foldIndexed( -// NumberedPolynomial( -// degs.mapIndexed { index, deg -> if (index in arg) 0U else deg } to c -// ) -// ) { index, acc, deg -> if (index in arg) multiplyWithPower(acc, arg[index]!!, deg) else acc } -// } -// .reduce { acc, polynomial -> acc + polynomial } // TODO: Rewrite. Might be slow. -// } -// -//// TODO: Substitute rational function -// -//public fun > NumberedPolynomial.asFunctionOver(ring: A): (Map) -> NumberedPolynomial = -// { substitute(ring, it) } -// -//public fun > NumberedPolynomial.asPolynomialFunctionOver(ring: A): (Map>) -> NumberedPolynomial = -// { substitute(ring, it) } - -//operator fun > Polynomial.div(other: T): Polynomial = -// if (other.isZero()) throw ArithmeticException("/ by zero") -// else -// Polynomial( -// coefficients -// .mapValues { it.value / other }, -// toCheckInput = false -// ) - -/** - * Evaluates the value of the given double polynomial for given double argument. - */ -public fun NumberedPolynomial.substitute(args: Map): NumberedPolynomial = Double.algebra { - val acc = LinkedHashMap, Double>(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()) - } - if (newDegs !in acc) acc[newDegs] = newC - else acc[newDegs] = acc[newDegs]!! + newC - } - return NumberedPolynomial(acc) -} - -/** - * Evaluates the value of the given polynomial for given argument. - * - * It is an implementation of [Horner's method](https://en.wikipedia.org/wiki/Horner%27s_method). - */ -public fun NumberedPolynomial.substitute(ring: Ring, args: Map): NumberedPolynomial = ring { - val acc = LinkedHashMap, C>(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) - } - if (newDegs !in acc) acc[newDegs] = newC - else acc[newDegs] = acc[newDegs]!! + newC - } - return NumberedPolynomial(acc) -} - -// TODO: (Waiting for hero) Replace with optimisation: the [result] may be unboxed, and all operations may be performed -// as soon as possible on it -@JvmName("substitutePolynomial") -public fun NumberedPolynomial.substitute(ring: Ring, args: Map>) : NumberedPolynomial = TODO() /*ring.numberedPolynomial { - val acc = LinkedHashMap, NumberedPolynomial>(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.asNumberedPolynomial()) { product, (variable, substitution) -> - val deg = degs.getOrElse(variable) { 0u } - if (deg == 0u) product else product * power(substitution, deg) - } - if (newDegs !in acc) acc[newDegs] = c.asNumberedPolynomial() - else acc[newDegs] = acc[newDegs]!! + c - } -}*/ - -/** - * Represent the polynomial as a regular context-less function. - */ -public fun > NumberedPolynomial.asFunction(ring: A): (Map) -> NumberedPolynomial = { substitute(ring, it) } - -/** - * Represent the polynomial as a regular context-less function. - */ -public fun > NumberedPolynomial.asPolynomialFunctionOver(ring: A): (Map>) -> NumberedPolynomial = { substitute(ring, it) } - -/** - * Returns algebraic derivative of received polynomial. - */ -@UnstableKMathAPI -public fun > NumberedPolynomial.derivativeWithRespectTo( - algebra: A, - variable: Int, -): NumberedPolynomial = algebra { - NumberedPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - if (degs.size > 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. - */ -@UnstableKMathAPI -public fun > NumberedPolynomial.derivativeWithRespectTo( - algebra: A, - variables: Collection, -): NumberedPolynomial = algebra { - val cleanedVariables = variables.toSet() - if (cleanedVariables.isEmpty()) return this@derivativeWithRespectTo - val maxRespectedVariable = cleanedVariables.maxOrNull()!! - NumberedPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - if (degs.size > maxRespectedVariable) return@forEach - put( - degs.mapIndexed { index, deg -> - when { - index !in cleanedVariables -> deg - deg > 0u -> deg - 1u - else -> return@forEach - } - }.cleanUp(), - cleanedVariables.fold(c) { acc, variable -> multiplyByDoubling(acc, degs[variable]) } - ) - } - } - ) -} - -/** - * Returns algebraic derivative of received polynomial. - */ -@UnstableKMathAPI -public fun > NumberedPolynomial.nthDerivativeWithRespectTo( - algebra: A, - variable: Int, - order: UInt -): NumberedPolynomial = algebra { - if (order == 0u) return this@nthDerivativeWithRespectTo - NumberedPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - if (degs.size > 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. - */ -@UnstableKMathAPI -public fun > NumberedPolynomial.nthDerivativeWithRespectTo( - algebra: A, - variablesAndOrders: Map, -): NumberedPolynomial = algebra { - 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.size > 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. - */ -@UnstableKMathAPI -public fun > NumberedPolynomial.antiderivativeWithRespectTo( - algebra: A, - variable: Int, -): NumberedPolynomial = algebra { - NumberedPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - put( - List(max(variable + 1, degs.size)) { if (it != variable) degs[it] else degs[it] + 1u }, - c / multiplyByDoubling(one, degs[variable]) - ) - } - } - ) -} - -/** - * Returns algebraic antiderivative of received polynomial. - */ -@UnstableKMathAPI -public fun > NumberedPolynomial.antiderivativeWithRespectTo( - algebra: A, - variables: Collection, -): NumberedPolynomial = algebra { - val cleanedVariables = variables.toSet() - if (cleanedVariables.isEmpty()) return this@antiderivativeWithRespectTo - val maxRespectedVariable = cleanedVariables.maxOrNull()!! - NumberedPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - put( - List(max(maxRespectedVariable + 1, degs.size)) { if (it !in variables) degs[it] else degs[it] + 1u }, - cleanedVariables.fold(c) { acc, variable -> acc / multiplyByDoubling(one, degs[variable]) } - ) - } - } - ) -} - -/** - * Returns algebraic derivative of received polynomial. - */ -@UnstableKMathAPI -public fun > NumberedPolynomial.nthAntiderivativeWithRespectTo( - algebra: A, - variable: Int, - order: UInt -): NumberedPolynomial = algebra { - if (order == 0u) return this@nthAntiderivativeWithRespectTo - NumberedPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - put( - List(max(variable + 1, degs.size)) { if (it != variable) degs[it] else degs[it] + order }, - degs[variable].let { deg -> - (deg downTo deg - order + 1u) - .fold(c) { acc, ord -> acc / multiplyByDoubling(one, ord) } - } - ) - } - } - ) -} - -/** - * Returns algebraic derivative of received polynomial. - */ -@UnstableKMathAPI -public fun > NumberedPolynomial.nthAntiderivativeWithRespectTo( - algebra: A, - variablesAndOrders: Map, -): NumberedPolynomial = algebra { - 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[it] + filteredVariablesAndOrders.getOrElse(it) { 0u } }, - filteredVariablesAndOrders.entries.fold(c) { acc1, (index, order) -> - degs[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-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt deleted file mode 100644 index 5cd0679ab..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.operations.Ring -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract - - -/** - * Creates a [NumberedRationalFunctionSpace] over a received ring. - */ -public fun > A.numberedRationalFunction(): NumberedRationalFunctionSpace = - NumberedRationalFunctionSpace(this) - -/** - * Creates a [NumberedRationalFunctionSpace]'s scope over a received ring. - */ -public inline fun , R> A.numberedRationalFunction(block: NumberedRationalFunctionSpace.() -> R): R { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return NumberedRationalFunctionSpace(this).block() -} - -//fun > NumberedRationalFunction.reduced(): NumberedRationalFunction { -// val greatestCommonDivider = polynomialGCD(numerator, denominator) -// return NumberedRationalFunction( -// numerator / greatestCommonDivider, -// denominator / greatestCommonDivider -// ) -//} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt deleted file mode 100644 index 0fcd4c6e5..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.integration - -import space.kscience.kmath.functions.PiecewisePolynomial -import space.kscience.kmath.functions.integrate -import space.kscience.kmath.functions.antiderivative -import space.kscience.kmath.interpolation.PolynomialInterpolator -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.structures.Buffer -import space.kscience.kmath.structures.DoubleBuffer -import space.kscience.kmath.structures.MutableBufferFactory - -/** - * Compute analytical indefinite integral of this [PiecewisePolynomial], keeping all intervals intact - */ -@OptIn(PerformancePitfall::class) -@UnstableKMathAPI -public fun > PiecewisePolynomial.integrate(algebra: Field): PiecewisePolynomial = - PiecewisePolynomial(pieces.map { it.first to it.second.antiderivative(algebra) }) - -/** - * Compute definite integral of given [PiecewisePolynomial] piece by piece in a given [range] - * Requires [UnivariateIntegrationNodes] or [IntegrationRange] and [IntegrandMaxCalls] - * - * TODO use context receiver for algebra - */ -@UnstableKMathAPI -public fun > PiecewisePolynomial.integrate( - algebra: Field, range: ClosedRange, -): T = algebra.sum( - pieces.map { (region, poly) -> - val intersectedRange = maxOf(range.start, region.start)..minOf(range.endInclusive, region.endInclusive) - //Check if polynomial range is not used - if (intersectedRange.start == intersectedRange.endInclusive) algebra.zero - else poly.integrate(algebra, intersectedRange) - } -) - -/** - * A generic spline-interpolation-based analytic integration - * * [IntegrationRange]—the univariate range of integration. By default, uses `0..1` interval. - * * [IntegrandMaxCalls]—the maximum number of function calls during integration. For non-iterative rules, always uses - * the maximum number of points. By default, uses 10 points. - */ -@UnstableKMathAPI -public class SplineIntegrator>( - public val algebra: Field, - public val bufferFactory: MutableBufferFactory, -) : UnivariateIntegrator { - override fun process(integrand: UnivariateIntegrand): UnivariateIntegrand = algebra { - val range = integrand.getFeature()?.range ?: 0.0..1.0 - - val interpolator: PolynomialInterpolator = SplineInterpolator(algebra, bufferFactory) - - val nodes: Buffer = integrand.getFeature()?.nodes ?: run { - val numPoints = integrand.getFeature()?.maxCalls ?: 100 - val step = (range.endInclusive - range.start) / (numPoints - 1) - DoubleBuffer(numPoints) { i -> range.start + i * step } - } - - val values = nodes.map(bufferFactory) { integrand.function(it) } - val polynomials = interpolator.interpolatePolynomials( - nodes.map(bufferFactory) { number(it) }, - values - ) - val res = polynomials.integrate(algebra, number(range.start)..number(range.endInclusive)) - integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + nodes.size) - } -} - -/** - * A simplified double-based spline-interpolation-based analytic integration - * * [IntegrationRange]—the univariate range of integration. By default, uses `0.0..1.0` interval. - * * [IntegrandMaxCalls]—the maximum number of function calls during integration. For non-iterative rules, always - * uses the maximum number of points. By default, uses 10 points. - */ -@UnstableKMathAPI -public object DoubleSplineIntegrator : UnivariateIntegrator { - override fun process(integrand: UnivariateIntegrand): UnivariateIntegrand { - val range = integrand.getFeature()?.range ?: 0.0..1.0 - val interpolator: PolynomialInterpolator = SplineInterpolator(DoubleField, ::DoubleBuffer) - - val nodes: Buffer = integrand.getFeature()?.nodes ?: run { - val numPoints = integrand.getFeature()?.maxCalls ?: 100 - val step = (range.endInclusive - range.start) / (numPoints - 1) - DoubleBuffer(numPoints) { i -> range.start + i * step } - } - - val values = nodes.map { integrand.function(it) } - val polynomials = interpolator.interpolatePolynomials(nodes, values) - val res = polynomials.integrate(DoubleField, range) - return integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + nodes.size) - } -} - -@Suppress("unused") -@UnstableKMathAPI -public inline val DoubleField.splineIntegrator: UnivariateIntegrator - get() = DoubleSplineIntegrator \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt deleted file mode 100644 index 62819be0c..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -@file:OptIn(UnstableKMathAPI::class) - -package space.kscience.kmath.interpolation - -import space.kscience.kmath.data.XYColumnarData -import space.kscience.kmath.functions.PiecewisePolynomial -import space.kscience.kmath.functions.asFunction -import space.kscience.kmath.functions.substitute -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.asBuffer - -/** - * And interpolator for data with x column type [X], y column type [Y]. - */ -public fun interface Interpolator { - public fun interpolate(points: XYColumnarData): (X) -> Y -} - -/** - * And interpolator returning [PiecewisePolynomial] function - */ -public interface PolynomialInterpolator> : Interpolator { - public val algebra: Ring - - public fun getDefaultValue(): T = error("Out of bounds") - - public fun interpolatePolynomials(points: XYColumnarData): PiecewisePolynomial - - override fun interpolate(points: XYColumnarData): (T) -> T = { x -> - interpolatePolynomials(points).substitute(algebra, x) ?: getDefaultValue() - } -} - - -public fun > PolynomialInterpolator.interpolatePolynomials( - x: Buffer, - y: Buffer, -): PiecewisePolynomial { - val pointSet = XYColumnarData.of(x, y) - return interpolatePolynomials(pointSet) -} - -public fun > PolynomialInterpolator.interpolatePolynomials( - data: Map, -): PiecewisePolynomial { - val pointSet = XYColumnarData.of(data.keys.toList().asBuffer(), data.values.toList().asBuffer()) - return interpolatePolynomials(pointSet) -} - -public fun > PolynomialInterpolator.interpolatePolynomials( - data: List>, -): PiecewisePolynomial { - val pointSet = XYColumnarData.of(data.map { it.first }.asBuffer(), data.map { it.second }.asBuffer()) - return interpolatePolynomials(pointSet) -} - -public fun > PolynomialInterpolator.interpolate( - x: Buffer, - y: Buffer, -): (T) -> T? = interpolatePolynomials(x, y).asFunction(algebra) - -public fun > PolynomialInterpolator.interpolate( - data: Map, -): (T) -> T? = interpolatePolynomials(data).asFunction(algebra) - -public fun > PolynomialInterpolator.interpolate( - data: List>, -): (T) -> T? = interpolatePolynomials(data).asFunction(algebra) - - -public fun > PolynomialInterpolator.interpolate( - x: Buffer, - y: Buffer, - defaultValue: T, -): (T) -> T = interpolatePolynomials(x, y).asFunction(algebra, defaultValue) - -public fun > PolynomialInterpolator.interpolate( - data: Map, - defaultValue: T, -): (T) -> T = interpolatePolynomials(data).asFunction(algebra, defaultValue) - -public fun > PolynomialInterpolator.interpolate( - data: List>, - defaultValue: T, -): (T) -> T = interpolatePolynomials(data).asFunction(algebra, defaultValue) \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt deleted file mode 100644 index b55f16cf2..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.interpolation - -import space.kscience.kmath.data.XYColumnarData -import space.kscience.kmath.functions.PiecewisePolynomial -import space.kscience.kmath.functions.ListPolynomial -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.Field -import space.kscience.kmath.operations.invoke - -@OptIn(UnstableKMathAPI::class) -internal fun > insureSorted(points: XYColumnarData<*, T, *>) { - for (i in 0 until points.size - 1) - require(points.x[i + 1] > points.x[i]) { "Input data is not sorted at index $i" } -} - -/** - * Reference JVM implementation: https://github.com/apache/commons-math/blob/master/src/main/java/org/apache/commons/math4/analysis/interpolation/LinearInterpolator.java - */ -public class LinearInterpolator>(override val algebra: Field) : PolynomialInterpolator { - - @OptIn(UnstableKMathAPI::class) - override fun interpolatePolynomials(points: XYColumnarData): PiecewisePolynomial = algebra { - require(points.size > 0) { "Point array should not be empty" } - insureSorted(points) - - PiecewisePolynomial(points.x[0]) { - for (i in 0 until points.size - 1) { - val slope = (points.y[i + 1] - points.y[i]) / (points.x[i + 1] - points.x[i]) - val const = points.y[i] - slope * points.x[i] - val polynomial = ListPolynomial(const, slope) - putRight(points.x[i + 1], polynomial) - } - } - } -} - -public val > Field.linearInterpolator: LinearInterpolator - get() = LinearInterpolator(this) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt deleted file mode 100644 index 48c90ff23..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.interpolation - -import space.kscience.kmath.data.XYColumnarData -import space.kscience.kmath.functions.PiecewisePolynomial -import space.kscience.kmath.functions.ListPolynomial -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.structures.DoubleBuffer -import space.kscience.kmath.structures.MutableBufferFactory - -/** - * Generic spline interpolator. Not recommended for performance critical places, use platform-specific and type - * specific ones. - * - * Based on - * https://github.com/apache/commons-math/blob/eb57d6d457002a0bb5336d789a3381a24599affe/src/main/java/org/apache/commons/math4/analysis/interpolation/SplineInterpolator.java - */ -public class SplineInterpolator>( - override val algebra: Field, - public val bufferFactory: MutableBufferFactory, -) : PolynomialInterpolator { - //TODO possibly optimize zeroed buffers - - @OptIn(UnstableKMathAPI::class) - override fun interpolatePolynomials(points: XYColumnarData): PiecewisePolynomial = algebra { - require(points.size >= 3) { "Can't use spline interpolator with less than 3 points" } - insureSorted(points) - // Number of intervals. The number of data points is n + 1. - val n = points.size - 1 - // Differences between knot points - val h = bufferFactory(n) { i -> points.x[i + 1] - points.x[i] } - val mu = bufferFactory(n) { zero } - val z = bufferFactory(n + 1) { zero } - - for (i in 1 until n) { - val g = 2.0 * (points.x[i + 1] - points.x[i - 1]) - h[i - 1] * mu[i - 1] - mu[i] = h[i] / g - z[i] = - ((points.y[i + 1] * h[i - 1] - points.y[i] * (points.x[i + 1] - points.x[i - 1]) + points.y[i - 1] * h[i]) * 3.0 / - (h[i - 1] * h[i]) - h[i - 1] * z[i - 1]) / g - } - - // cubic spline coefficients -- b is linear, c quadratic, d is cubic (original y's are constants) - - PiecewisePolynomial(points.x[points.size - 1]) { - var cOld = zero - - for (j in n - 1 downTo 0) { - val c = z[j] - mu[j] * cOld - val a = points.y[j] - val b = (points.y[j + 1] - points.y[j]) / h[j] - h[j] * (cOld + 2.0 * c) / 3.0 - val d = (cOld - c) / (3.0 * h[j]) - val x0 = points.x[j] - val x02 = x0 * x0 - val x03 = x02 * x0 - //Shift coefficients to represent absolute polynomial instead of one with an offset - val polynomial = ListPolynomial( - a - b * x0 + c * x02 - d * x03, - b - 2 * c * x0 + 3 * d * x02, - c - 3 * d * x0, - d - ) - cOld = c - putLeft(x0, polynomial) - } - } - } -} - - -public fun > Field.splineInterpolator( - bufferFactory: MutableBufferFactory, -): SplineInterpolator = SplineInterpolator(this, bufferFactory) - -public val DoubleField.splineInterpolator: SplineInterpolator - get() = SplineInterpolator(this, ::DoubleBuffer) \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt deleted file mode 100644 index aae0ad017..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.integration - -import space.kscience.kmath.functions.ListPolynomial -import space.kscience.kmath.functions.integrate -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.DoubleField -import kotlin.math.PI -import kotlin.math.sin -import kotlin.test.Test -import kotlin.test.assertEquals - -@OptIn(UnstableKMathAPI::class) -class SplineIntegralTest { - - @Test - fun integratePolynomial(){ - val polynomial = ListPolynomial(1.0, 2.0, 3.0) - val integral = polynomial.integrate(DoubleField,1.0..2.0) - assertEquals(11.0, integral, 0.001) - } - - @Test - fun gaussSin() { - val res = DoubleField.splineIntegrator.integrate(0.0..2 * PI, IntegrandMaxCalls(5)) { x -> - sin(x) - } - assertEquals(0.0, res.value, 1e-2) - } - - @Test - fun gaussUniform() { - val res = DoubleField.splineIntegrator.integrate(35.0..100.0, IntegrandMaxCalls(20)) { x -> - if(x in 30.0..50.0){ - 1.0 - } else { - 0.0 - } - } - assertEquals(15.0, res.value, 0.5) - } - - -} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt deleted file mode 100644 index 1143036d4..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.interpolation - -import space.kscience.kmath.operations.DoubleField -import kotlin.test.Test -import kotlin.test.assertEquals - -internal class LinearInterpolatorTest { - @Test - fun testInterpolation() { - val data = listOf( - 0.0 to 0.0, - 1.0 to 1.0, - 2.0 to 3.0, - 3.0 to 4.0 - ) - - //val polynomial: PiecewisePolynomial = DoubleField.linearInterpolator.interpolatePolynomials(data) - val function = DoubleField.linearInterpolator.interpolate(data) - assertEquals(null, function(-1.0)) - assertEquals(0.5, function(0.5)) - assertEquals(2.0, function(1.5)) - assertEquals(3.0, function(2.0)) - } -} diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt deleted file mode 100644 index 4c7d816d4..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.interpolation - -import space.kscience.kmath.operations.DoubleField -import kotlin.math.PI -import kotlin.math.sin -import kotlin.test.Test -import kotlin.test.assertEquals - -internal class SplineInterpolatorTest { - @Test - fun testInterpolation() { - val data = (0..10).map { - val x = it.toDouble() / 5 * PI - x to sin(x) - } - - //val polynomial: PiecewisePolynomial = DoubleField.splineInterpolator.interpolatePolynomials(data) - - val function = DoubleField.splineInterpolator.interpolate(data, Double.NaN) - - assertEquals(Double.NaN, function(-1.0)) - assertEquals(sin(0.5), function(0.5), 0.1) - assertEquals(sin(1.5), function(1.5), 0.1) - assertEquals(sin(2.0), function(2.0), 0.1) - } -} diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt deleted file mode 100644 index 2353beee6..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.test.misc - -import space.kscience.kmath.functions.ListPolynomial -import space.kscience.kmath.functions.ListPolynomialSpace -import space.kscience.kmath.misc.UnstableKMathAPI -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(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", "NOTHING_TO_INLINE") -@OptIn(UnstableKMathAPI::class) -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(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 -} - -fun ListPolynomialSpace.number(arg: Int) = IntModulo(arg, ring.modulus, toCheckInput = false) - -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) }) \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt deleted file mode 100644 index 72bb5942c..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.test.misc - -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.Field -import space.kscience.kmath.operations.NumbersAddOps - -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 = - Rational( - numerator * other.denominator + denominator * other.numerator, - denominator * other.denominator - ) - operator fun plus(other: Int): Rational = - Rational( - numerator + denominator * other.toLong(), - denominator - ) - operator fun plus(other: Long): Rational = - Rational( - numerator + denominator * other, - denominator - ) - operator fun minus(other: Rational): Rational = - Rational( - numerator * other.denominator - denominator * other.numerator, - denominator * other.denominator - ) - operator fun minus(other: Int): Rational = - Rational( - numerator - denominator * other.toLong(), - denominator - ) - operator fun minus(other: Long): Rational = - Rational( - numerator - denominator * other, - denominator - ) - operator fun times(other: Rational): Rational = - Rational( - numerator * other.numerator, - denominator * other.denominator - ) - operator fun times(other: Int): Rational = - Rational( - numerator * other.toLong(), - denominator - ) - operator fun times(other: Long): Rational = - Rational( - numerator * other, - denominator - ) - operator fun div(other: Rational): Rational = - Rational( - numerator * other.denominator, - denominator * other.numerator - ) - operator fun div(other: Int): Rational = - Rational( - numerator, - denominator * other.toLong() - ) - operator fun div(other: Long): Rational = - Rational( - numerator, - denominator * other - ) - 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", "NOTHING_TO_INLINE") -@OptIn(UnstableKMathAPI::class) -object RationalField : Field, NumbersAddOps { - override inline val zero: Rational get() = Rational.ZERO - override inline val one: Rational get() = Rational.ONE - - override inline fun number(value: Number): Rational = Rational(value.toLong()) - - override inline fun add(left: Rational, right: Rational): Rational = left + right - override inline fun multiply(left: Rational, right: Rational): Rational = left * right - override inline fun divide(left: Rational, right: Rational): Rational = left / right - override inline fun scale(a: Rational, value: Double): Rational = a * number(value) - - override inline fun Rational.unaryMinus(): Rational = -this - override inline fun Rational.plus(arg: Rational): Rational = this + arg - override inline fun Rational.minus(arg: Rational): Rational = this - arg - override inline fun Rational.times(arg: Rational): Rational = this * arg - override inline fun Rational.div(arg: Rational): Rational = this / arg -} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/RationalWithMemorization.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/RationalWithMemorization.kt deleted file mode 100644 index 05d9115fa..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/RationalWithMemorization.kt +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.test.misc - -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.* - -class RationalWithMemorization private constructor( - val value: Rational, - override val memory : OperationsMemory -): WithMemorization { - companion object { - /** - * Constant containing the zero (the additive identity) of the [Rational] field. - */ - public val ZERO: RationalWithMemorization = RationalWithMemorization(Rational.ZERO, object : Endpoint {}) - /** - * Constant containing the one (the multiplicative identity) of the [Rational] field. - */ - public val ONE: RationalWithMemorization = RationalWithMemorization(Rational.ONE, object : Endpoint {}) - } - constructor(numerator: Int, denominator: Int) : this(Rational(numerator, denominator), object : Endpoint {}) - constructor(numerator: Int, denominator: Long) : this(Rational(numerator, denominator), object : Endpoint {}) - constructor(numerator: Long, denominator: Int) : this(Rational(numerator, denominator), object : Endpoint {}) - constructor(numerator: Long, denominator: Long) : this(Rational(numerator, denominator), object : Endpoint {}) - constructor(numerator: Int) : this(Rational(numerator), object : Endpoint {}) - constructor(numerator: Long) : this(Rational(numerator), object : Endpoint {}) - - operator fun unaryPlus(): RationalWithMemorization = this - operator fun unaryMinus(): RationalWithMemorization = RationalWithMemorization( - -value, - object : Negation { - override val negated: OperationsMemory = memory - } - ) - operator fun plus(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization( - value + other.value, - object : Sum { - override val augend: OperationsMemory = memory - override val addend: OperationsMemory = other.memory - } - ) - operator fun minus(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization( - value - other.value, - object : Difference { - override val minuend: OperationsMemory = memory - override val subtrahend: OperationsMemory = other.memory - } - ) - operator fun times(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization( - value * other.value, - object : Product { - override val multiplicand: OperationsMemory = memory - override val multiplier: OperationsMemory = other.memory - } - ) - operator fun div(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization( - value / other.value, - object : Quotient { - override val dividend: OperationsMemory = memory - override val divisor: OperationsMemory = other.memory - } - ) - - override fun equals(other: Any?): Boolean = - other is RationalWithMemorization && value == other.value - - override fun hashCode(): Int = value.hashCode() - - override fun toString(): String = value.toString() -} - -@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -object RationalWithMemorizationRing : Ring { - override inline val zero: RationalWithMemorization get() = RationalWithMemorization.ZERO - override inline val one: RationalWithMemorization get() = RationalWithMemorization.ONE - - override inline fun add(left: RationalWithMemorization, right: RationalWithMemorization): RationalWithMemorization = left + right - override inline fun multiply(left: RationalWithMemorization, right: RationalWithMemorization): RationalWithMemorization = left * right - - override inline fun RationalWithMemorization.unaryMinus(): RationalWithMemorization = -this - override inline fun RationalWithMemorization.plus(arg: RationalWithMemorization): RationalWithMemorization = this + arg - override inline fun RationalWithMemorization.minus(arg: RationalWithMemorization): RationalWithMemorization = this - arg - override inline fun RationalWithMemorization.times(arg: RationalWithMemorization): RationalWithMemorization = this * arg -} - -@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -object RationalWithMemorizationField : Field { - override inline val zero: RationalWithMemorization get() = RationalWithMemorization.ZERO - override inline val one: RationalWithMemorization get() = RationalWithMemorization.ONE - - override inline fun number(value: Number): RationalWithMemorization = RationalWithMemorization(value.toLong()) - - override inline fun add(left: RationalWithMemorization, right: RationalWithMemorization): RationalWithMemorization = left + right - override inline fun multiply(left: RationalWithMemorization, right: RationalWithMemorization): RationalWithMemorization = left * right - override inline fun divide(left: RationalWithMemorization, right: RationalWithMemorization): RationalWithMemorization = left / right - override inline fun scale(a: RationalWithMemorization, value: Double): RationalWithMemorization = a * number(value) - - override inline fun RationalWithMemorization.unaryMinus(): RationalWithMemorization = -this - override inline fun RationalWithMemorization.plus(arg: RationalWithMemorization): RationalWithMemorization = this + arg - override inline fun RationalWithMemorization.minus(arg: RationalWithMemorization): RationalWithMemorization = this - arg - override inline fun RationalWithMemorization.times(arg: RationalWithMemorization): RationalWithMemorization = this * arg - override inline fun RationalWithMemorization.div(arg: RationalWithMemorization): RationalWithMemorization = this / arg -} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/memorization.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/memorization.kt deleted file mode 100644 index a4fb81274..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/memorization.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.test.misc - -sealed interface OperationsMemory - -interface Endpoint: OperationsMemory - -interface Negation: OperationsMemory { - val negated: OperationsMemory -} - -interface Sum: OperationsMemory { - val augend: OperationsMemory - val addend: OperationsMemory -} - -interface Difference: OperationsMemory { - val minuend: OperationsMemory - val subtrahend: OperationsMemory -} - -interface Product: OperationsMemory { - val multiplicand: OperationsMemory - val multiplier: OperationsMemory -} - -interface Quotient: OperationsMemory { - val dividend: OperationsMemory - val divisor: OperationsMemory -} - - -fun equalMemories(one: OperationsMemory, other: OperationsMemory) : Boolean = - when(one) { - is Negation -> other is Negation && equalMemories(one.negated, other.negated) - is Sum -> other is Sum && equalMemories(one.augend, other.augend) && equalMemories(one.addend, other.addend) - is Difference -> other is Difference && equalMemories(one.minuend, other.minuend) && equalMemories(one.subtrahend, other.subtrahend) - is Product -> other is Product && equalMemories(one.multiplicand, other.multiplicand) && equalMemories(one.multiplier, other.multiplier) - is Quotient -> other is Quotient && equalMemories(one.dividend, other.dividend) && equalMemories(one.divisor, other.divisor) - is Endpoint -> one === other - } - -interface WithMemorization { - val memory: OperationsMemory -} - -fun equalMemories(one: WithMemorization, other: WithMemorization) : Boolean = equalMemories(one.memory, other.memory) \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt deleted file mode 100644 index cc647fa2c..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.test.misc - -// TODO: Move to corresponding module "kmath-number-theory" - -import kotlin.math.abs - - -data class BezoutIdentityWithGCD(val first: T, val second: T, val gcd: T) - -tailrec fun gcd(a: Long, b: Long): Long = if (a == 0L) abs(b) else gcd(b % a, a) - -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 -- 2.34.1 From a6b86eeee122ce42229ccef2fb3372828e36b3bc Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sat, 11 Jun 2022 19:31:01 +0300 Subject: [PATCH 078/275] Cleaned out useless code. --- .../kscience/kmath/test/misc/IntModulo.kt | 142 ------------------ .../kscience/kmath/test/misc/Rational.kt | 135 ----------------- .../test/misc/RationalWithMemorization.kt | 107 ------------- .../kscience/kmath/test/misc/memorization.kt | 51 ------- .../space/kscience/kmath/test/misc/misc.kt | 31 ---- 5 files changed, 466 deletions(-) delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/RationalWithMemorization.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/memorization.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt deleted file mode 100644 index 2353beee6..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.test.misc - -import space.kscience.kmath.functions.ListPolynomial -import space.kscience.kmath.functions.ListPolynomialSpace -import space.kscience.kmath.misc.UnstableKMathAPI -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(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", "NOTHING_TO_INLINE") -@OptIn(UnstableKMathAPI::class) -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(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 -} - -fun ListPolynomialSpace.number(arg: Int) = IntModulo(arg, ring.modulus, toCheckInput = false) - -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) }) \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt deleted file mode 100644 index 72bb5942c..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.test.misc - -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.Field -import space.kscience.kmath.operations.NumbersAddOps - -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 = - Rational( - numerator * other.denominator + denominator * other.numerator, - denominator * other.denominator - ) - operator fun plus(other: Int): Rational = - Rational( - numerator + denominator * other.toLong(), - denominator - ) - operator fun plus(other: Long): Rational = - Rational( - numerator + denominator * other, - denominator - ) - operator fun minus(other: Rational): Rational = - Rational( - numerator * other.denominator - denominator * other.numerator, - denominator * other.denominator - ) - operator fun minus(other: Int): Rational = - Rational( - numerator - denominator * other.toLong(), - denominator - ) - operator fun minus(other: Long): Rational = - Rational( - numerator - denominator * other, - denominator - ) - operator fun times(other: Rational): Rational = - Rational( - numerator * other.numerator, - denominator * other.denominator - ) - operator fun times(other: Int): Rational = - Rational( - numerator * other.toLong(), - denominator - ) - operator fun times(other: Long): Rational = - Rational( - numerator * other, - denominator - ) - operator fun div(other: Rational): Rational = - Rational( - numerator * other.denominator, - denominator * other.numerator - ) - operator fun div(other: Int): Rational = - Rational( - numerator, - denominator * other.toLong() - ) - operator fun div(other: Long): Rational = - Rational( - numerator, - denominator * other - ) - 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", "NOTHING_TO_INLINE") -@OptIn(UnstableKMathAPI::class) -object RationalField : Field, NumbersAddOps { - override inline val zero: Rational get() = Rational.ZERO - override inline val one: Rational get() = Rational.ONE - - override inline fun number(value: Number): Rational = Rational(value.toLong()) - - override inline fun add(left: Rational, right: Rational): Rational = left + right - override inline fun multiply(left: Rational, right: Rational): Rational = left * right - override inline fun divide(left: Rational, right: Rational): Rational = left / right - override inline fun scale(a: Rational, value: Double): Rational = a * number(value) - - override inline fun Rational.unaryMinus(): Rational = -this - override inline fun Rational.plus(arg: Rational): Rational = this + arg - override inline fun Rational.minus(arg: Rational): Rational = this - arg - override inline fun Rational.times(arg: Rational): Rational = this * arg - override inline fun Rational.div(arg: Rational): Rational = this / arg -} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/RationalWithMemorization.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/RationalWithMemorization.kt deleted file mode 100644 index 05d9115fa..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/RationalWithMemorization.kt +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.test.misc - -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.* - -class RationalWithMemorization private constructor( - val value: Rational, - override val memory : OperationsMemory -): WithMemorization { - companion object { - /** - * Constant containing the zero (the additive identity) of the [Rational] field. - */ - public val ZERO: RationalWithMemorization = RationalWithMemorization(Rational.ZERO, object : Endpoint {}) - /** - * Constant containing the one (the multiplicative identity) of the [Rational] field. - */ - public val ONE: RationalWithMemorization = RationalWithMemorization(Rational.ONE, object : Endpoint {}) - } - constructor(numerator: Int, denominator: Int) : this(Rational(numerator, denominator), object : Endpoint {}) - constructor(numerator: Int, denominator: Long) : this(Rational(numerator, denominator), object : Endpoint {}) - constructor(numerator: Long, denominator: Int) : this(Rational(numerator, denominator), object : Endpoint {}) - constructor(numerator: Long, denominator: Long) : this(Rational(numerator, denominator), object : Endpoint {}) - constructor(numerator: Int) : this(Rational(numerator), object : Endpoint {}) - constructor(numerator: Long) : this(Rational(numerator), object : Endpoint {}) - - operator fun unaryPlus(): RationalWithMemorization = this - operator fun unaryMinus(): RationalWithMemorization = RationalWithMemorization( - -value, - object : Negation { - override val negated: OperationsMemory = memory - } - ) - operator fun plus(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization( - value + other.value, - object : Sum { - override val augend: OperationsMemory = memory - override val addend: OperationsMemory = other.memory - } - ) - operator fun minus(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization( - value - other.value, - object : Difference { - override val minuend: OperationsMemory = memory - override val subtrahend: OperationsMemory = other.memory - } - ) - operator fun times(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization( - value * other.value, - object : Product { - override val multiplicand: OperationsMemory = memory - override val multiplier: OperationsMemory = other.memory - } - ) - operator fun div(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization( - value / other.value, - object : Quotient { - override val dividend: OperationsMemory = memory - override val divisor: OperationsMemory = other.memory - } - ) - - override fun equals(other: Any?): Boolean = - other is RationalWithMemorization && value == other.value - - override fun hashCode(): Int = value.hashCode() - - override fun toString(): String = value.toString() -} - -@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -object RationalWithMemorizationRing : Ring { - override inline val zero: RationalWithMemorization get() = RationalWithMemorization.ZERO - override inline val one: RationalWithMemorization get() = RationalWithMemorization.ONE - - override inline fun add(left: RationalWithMemorization, right: RationalWithMemorization): RationalWithMemorization = left + right - override inline fun multiply(left: RationalWithMemorization, right: RationalWithMemorization): RationalWithMemorization = left * right - - override inline fun RationalWithMemorization.unaryMinus(): RationalWithMemorization = -this - override inline fun RationalWithMemorization.plus(arg: RationalWithMemorization): RationalWithMemorization = this + arg - override inline fun RationalWithMemorization.minus(arg: RationalWithMemorization): RationalWithMemorization = this - arg - override inline fun RationalWithMemorization.times(arg: RationalWithMemorization): RationalWithMemorization = this * arg -} - -@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -object RationalWithMemorizationField : Field { - override inline val zero: RationalWithMemorization get() = RationalWithMemorization.ZERO - override inline val one: RationalWithMemorization get() = RationalWithMemorization.ONE - - override inline fun number(value: Number): RationalWithMemorization = RationalWithMemorization(value.toLong()) - - override inline fun add(left: RationalWithMemorization, right: RationalWithMemorization): RationalWithMemorization = left + right - override inline fun multiply(left: RationalWithMemorization, right: RationalWithMemorization): RationalWithMemorization = left * right - override inline fun divide(left: RationalWithMemorization, right: RationalWithMemorization): RationalWithMemorization = left / right - override inline fun scale(a: RationalWithMemorization, value: Double): RationalWithMemorization = a * number(value) - - override inline fun RationalWithMemorization.unaryMinus(): RationalWithMemorization = -this - override inline fun RationalWithMemorization.plus(arg: RationalWithMemorization): RationalWithMemorization = this + arg - override inline fun RationalWithMemorization.minus(arg: RationalWithMemorization): RationalWithMemorization = this - arg - override inline fun RationalWithMemorization.times(arg: RationalWithMemorization): RationalWithMemorization = this * arg - override inline fun RationalWithMemorization.div(arg: RationalWithMemorization): RationalWithMemorization = this / arg -} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/memorization.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/memorization.kt deleted file mode 100644 index a4fb81274..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/memorization.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.test.misc - -sealed interface OperationsMemory - -interface Endpoint: OperationsMemory - -interface Negation: OperationsMemory { - val negated: OperationsMemory -} - -interface Sum: OperationsMemory { - val augend: OperationsMemory - val addend: OperationsMemory -} - -interface Difference: OperationsMemory { - val minuend: OperationsMemory - val subtrahend: OperationsMemory -} - -interface Product: OperationsMemory { - val multiplicand: OperationsMemory - val multiplier: OperationsMemory -} - -interface Quotient: OperationsMemory { - val dividend: OperationsMemory - val divisor: OperationsMemory -} - - -fun equalMemories(one: OperationsMemory, other: OperationsMemory) : Boolean = - when(one) { - is Negation -> other is Negation && equalMemories(one.negated, other.negated) - is Sum -> other is Sum && equalMemories(one.augend, other.augend) && equalMemories(one.addend, other.addend) - is Difference -> other is Difference && equalMemories(one.minuend, other.minuend) && equalMemories(one.subtrahend, other.subtrahend) - is Product -> other is Product && equalMemories(one.multiplicand, other.multiplicand) && equalMemories(one.multiplier, other.multiplier) - is Quotient -> other is Quotient && equalMemories(one.dividend, other.dividend) && equalMemories(one.divisor, other.divisor) - is Endpoint -> one === other - } - -interface WithMemorization { - val memory: OperationsMemory -} - -fun equalMemories(one: WithMemorization, other: WithMemorization) : Boolean = equalMemories(one.memory, other.memory) \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt deleted file mode 100644 index cc647fa2c..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.test.misc - -// TODO: Move to corresponding module "kmath-number-theory" - -import kotlin.math.abs - - -data class BezoutIdentityWithGCD(val first: T, val second: T, val gcd: T) - -tailrec fun gcd(a: Long, b: Long): Long = if (a == 0L) abs(b) else gcd(b % a, a) - -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 -- 2.34.1 From 17703e407dd33dcddff3608c9a8fa06c052af8d7 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sun, 12 Jun 2022 00:24:23 +0300 Subject: [PATCH 079/275] Applied changes from previous sift. --- .../kscience/kmath/functions/Polynomial.kt | 150 ++++-- .../kmath/functions/RationalFunction.kt | 467 +++++++++++++----- 2 files changed, 468 insertions(+), 149 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index e201f1f6e..f2eba10d5 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -25,38 +25,38 @@ public interface Polynomial @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 constant (member of underlying 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]. */ public operator fun C.plus(other: Int): C /** - * Returns difference between the constant and the integer represented as constant (member of underlying ring). + * 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]. */ public operator fun C.minus(other: Int): C /** - * Returns product of the constant and the integer represented as constant (member of underlying ring). + * 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]. */ public operator fun C.times(other: Int): C /** - * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public operator fun Int.plus(other: C): C /** - * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public operator fun Int.minus(other: C): C /** - * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ @@ -72,38 +72,38 @@ public interface PolynomialSpace> : Ring

{ public fun Int.asConstant(): C = constantNumber(this) /** - * Returns sum of the polynomial and the integer represented as polynomial. + * 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 polynomial. + * 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 polynomial. + * 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 polynomial and the polynomial. + * 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 polynomial and the polynomial. + * 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 polynomial and the polynomial. + * Returns product of the integer represented as a polynomial and the polynomial. * * The operation is equivalent to sum of [this] copies of [other]. */ @@ -165,28 +165,28 @@ public interface PolynomialSpace> : Ring

{ public val constantOne: C /** - * Returns sum of the constant represented as polynomial and the polynomial. + * Returns sum of the constant represented as a polynomial and the polynomial. */ public operator fun C.plus(other: P): P /** - * Returns difference between the constant represented as polynomial and the polynomial. + * Returns difference between the constant represented as a polynomial and the polynomial. */ public operator fun C.minus(other: P): P /** - * Returns product of the constant represented as polynomial and the polynomial. + * Returns product of the constant represented as a polynomial and the polynomial. */ public operator fun C.times(other: P): P /** - * Returns sum of the constant represented as polynomial and the polynomial. + * Returns sum of the constant represented as a polynomial and the polynomial. */ public operator fun P.plus(other: C): P /** - * Returns difference between the constant represented as polynomial and the polynomial. + * Returns difference between the constant represented as a polynomial and the polynomial. */ public operator fun P.minus(other: C): P /** - * Returns product of the constant represented as polynomial and the polynomial. + * Returns product of the constant represented as a polynomial and the polynomial. */ public operator fun P.times(other: C): P @@ -254,41 +254,44 @@ public interface PolynomialSpace> : Ring

{ @Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 public interface PolynomialSpaceOverRing, A: Ring> : 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 constant (member of underlying 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]. */ 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 constant (member of underlying ring). + * 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]. */ 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 constant (member of underlying ring). + * 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]. */ public override operator fun C.times(other: Int): C = ring { multiplyByDoubling(this@times, other) } /** - * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public override operator fun Int.plus(other: C): C = ring { addMultipliedByDoubling(other, one, this@plus) } /** - * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public override operator fun Int.minus(other: C): C = ring { addMultipliedByDoubling(-other, one, this@minus) } /** - * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ @@ -330,58 +333,143 @@ public interface PolynomialSpaceOverRing, A: Ring> : Poly 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") 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") 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") 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") 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") 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") public operator fun Int.times(other: V): P - @JvmName("plusConstantVariable") - public operator fun C.plus(other: V): P - @JvmName("minusConstantVariable") - public operator fun C.minus(other: V): P - @JvmName("timesConstantVariable") - public operator fun C.times(other: V): P - + /** + * Returns sum of the variable represented as a monic monomial and the constant represented as a constant polynomial. + */ @JvmName("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") 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") 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") + 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") + 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") + 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. + */ + public fun number(variable: V): P = +variable + /** + * Represents the variable as a monic monomial. + */ + 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 diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index dfec126f3..edc9dfa5c 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -25,44 +25,44 @@ public interface RationalFunction> { * [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 in them. + * @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 RationalFunctionalSpace, R: RationalFunction> : Ring { /** - * Returns sum of the constant and the integer represented as constant (member of underlying 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]. */ public operator fun C.plus(other: Int): C /** - * Returns difference between the constant and the integer represented as constant (member of underlying ring). + * 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]. */ public operator fun C.minus(other: Int): C /** - * Returns product of the constant and the integer represented as constant (member of underlying ring). + * 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]. */ public operator fun C.times(other: Int): C /** - * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public operator fun Int.plus(other: C): C /** - * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public operator fun Int.minus(other: C): C /** - * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ @@ -78,38 +78,38 @@ public interface RationalFunctionalSpace, R: RationalFunctio public fun Int.asConstant(): C = constantNumber(this) /** - * Returns sum of the constant and the integer represented as polynomial. + * 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]. */ public operator fun P.plus(other: Int): P /** - * Returns difference between the constant and the integer represented as polynomial. + * 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]. */ public operator fun P.minus(other: Int): P /** - * Returns product of the constant and the integer represented as polynomial. + * Returns product of the constant 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 /** - * Returns sum of the integer represented as polynomial and the constant. + * 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]. */ public operator fun Int.plus(other: P): P /** - * Returns difference between the integer represented as polynomial and the constant. + * 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]. */ public operator fun Int.minus(other: P): P /** - * Returns product of the integer represented as polynomial and the constant. + * Returns product of the integer represented as a polynomial and the constant. * * The operation is equivalent to sum of [this] copies of [other]. */ @@ -125,25 +125,25 @@ public interface RationalFunctionalSpace, R: RationalFunctio public fun Int.asPolynomial(): P = polynomialNumber(this) /** - * Returns sum of the rational function and the integer represented as rational function. + * 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 rational function. + * 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 rational function. + * 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 rational function. + * 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]. @@ -151,25 +151,25 @@ public interface RationalFunctionalSpace, R: RationalFunctio public operator fun R.div(other: Int): R = this / multiplyByDoubling(one, other) /** - * Returns sum of the integer represented as rational function and the rational function. + * 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 rational function and the rational function. + * 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 rational function and the rational function. + * 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 rational function and the rational function. + * 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. @@ -232,28 +232,28 @@ public interface RationalFunctionalSpace, R: RationalFunctio public val constantOne: C /** - * Returns sum of the constant represented as polynomial and the polynomial. + * Returns sum of the constant represented as a polynomial and the polynomial. */ public operator fun C.plus(other: P): P /** - * Returns difference between the constant represented as polynomial and the polynomial. + * Returns difference between the constant represented as a polynomial and the polynomial. */ public operator fun C.minus(other: P): P /** - * Returns product of the constant represented as polynomial and the polynomial. + * Returns product of the constant represented as a polynomial and the polynomial. */ public operator fun C.times(other: P): P /** - * Returns sum of the constant represented as polynomial and the polynomial. + * Returns sum of the constant represented as a polynomial and the polynomial. */ public operator fun P.plus(other: C): P /** - * Returns difference between the constant represented as polynomial and the polynomial. + * Returns difference between the constant represented as a polynomial and the polynomial. */ public operator fun P.minus(other: C): P /** - * Returns product of the constant represented as polynomial and the polynomial. + * Returns product of the constant represented as a polynomial and the polynomial. */ public operator fun P.times(other: C): P @@ -305,36 +305,36 @@ public interface RationalFunctionalSpace, R: RationalFunctio public val polynomialOne: P /** - * Returns sum of the constant represented as rational function and the rational function. + * Returns sum of the constant represented as a rational function and the rational function. */ public operator fun C.plus(other: R): R /** - * Returns difference between the constant represented as polynomial and the rational function. + * Returns difference between the constant represented as a polynomial and the rational function. */ public operator fun C.minus(other: R): R /** - * Returns product of the constant represented as polynomial and the rational function. + * Returns product of the constant represented as a polynomial and the rational function. */ public operator fun C.times(other: R): R /** - * Returns quotient of the constant represented as polynomial and the rational function. + * Returns quotient of the constant represented as a polynomial and the rational function. */ public operator fun C.div(other: R): R /** - * Returns sum of the rational function and the constant represented as rational function. + * Returns sum of the rational function and the constant represented as a rational function. */ public operator fun R.plus(other: C): R /** - * Returns difference between the rational function and the constant represented as rational function. + * Returns difference between the rational function and the constant represented as a rational function. */ public operator fun R.minus(other: C): R /** - * Returns product of the rational function and the constant represented as rational function. + * Returns product of the rational function and the constant represented as a rational function. */ public operator fun R.times(other: C): R /** - * Returns quotient of the rational function and the constant represented as rational function. + * Returns quotient of the rational function and the constant represented as a rational function. */ public operator fun R.div(other: C): R @@ -348,36 +348,36 @@ public interface RationalFunctionalSpace, R: RationalFunctio public fun C.asRationalFunction(): R = number(this) /** - * Returns sum of the polynomial represented as rational function and the rational function. + * Returns sum of the polynomial represented as a rational function and the rational function. */ public operator fun P.plus(other: R): R /** - * Returns difference between the polynomial represented as polynomial and the rational function. + * Returns difference between the polynomial represented as a polynomial and the rational function. */ public operator fun P.minus(other: R): R /** - * Returns product of the polynomial represented as polynomial and the rational function. + * Returns product of the polynomial represented as a polynomial and the rational function. */ public operator fun P.times(other: R): R /** - * Returns quotient of the polynomial represented as polynomial and the rational function. + * Returns quotient of the polynomial represented as a polynomial and the rational function. */ public operator fun P.div(other: R): R /** - * Returns sum of the rational function and the polynomial represented as rational function. + * Returns sum of the rational function and the polynomial represented as a rational function. */ public operator fun R.plus(other: P): R /** - * Returns difference between the rational function and the polynomial represented as rational function. + * Returns difference between the rational function and the polynomial represented as a rational function. */ public operator fun R.minus(other: P): R /** - * Returns product of the rational function and the polynomial represented as rational function. + * Returns product of the rational function and the polynomial represented as a rational function. */ public operator fun R.times(other: P): R /** - * Returns quotient of the rational function and the polynomial represented as rational function. + * Returns quotient of the rational function and the polynomial represented as a rational function. */ public operator fun R.div(other: P): R @@ -459,43 +459,51 @@ public interface RationalFunctionalSpace, R: RationalFunctio * @param A the type of algebraic structure (precisely, of ring) provided for constants. */ @Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 -public interface RationalFunctionalSpaceOverRing, R: RationalFunction, A: Ring> : RationalFunctionalSpace { +public interface RationalFunctionalSpaceOverRing< + C, + P: Polynomial, + R: RationalFunction, + A: Ring + > : RationalFunctionalSpace { + /** + * 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 constant (member of underlying 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]. */ 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 constant (member of underlying ring). + * 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]. */ 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 constant (member of underlying ring). + * 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]. */ public override operator fun C.times(other: Int): C = ring { multiplyByDoubling(this@times, other) } /** - * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public override operator fun Int.plus(other: C): C = ring { addMultipliedByDoubling(other, one, this@plus) } /** - * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public override operator fun Int.minus(other: C): C = ring { addMultipliedByDoubling(-other, one, this@minus) } /** - * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ @@ -560,41 +568,44 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< AP: PolynomialSpace, > : RationalFunctionalSpace { + /** + * 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 constant (member of underlying 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]. */ public override operator fun C.plus(other: Int): C = polynomialRing { this@plus + other } /** - * Returns difference between the constant and the integer represented as constant (member of underlying ring). + * 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]. */ public override operator fun C.minus(other: Int): C = polynomialRing { this@minus - other } /** - * Returns product of the constant and the integer represented as constant (member of underlying ring). + * 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]. */ public override operator fun C.times(other: Int): C = polynomialRing { this@times * other } /** - * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public override operator fun Int.plus(other: C): C = polynomialRing { this@plus + other } /** - * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public override operator fun Int.minus(other: C): C = polynomialRing { this@minus - other } /** - * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ @@ -610,38 +621,38 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< override fun Int.asConstant(): C = polynomialRing { asConstant() } /** - * Returns sum of the constant and the integer represented as polynomial. + * 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]. */ public override operator fun P.plus(other: Int): P = polynomialRing { this@plus + other } /** - * Returns difference between the constant and the integer represented as polynomial. + * 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]. */ public override operator fun P.minus(other: Int): P = polynomialRing { this@minus - other } /** - * Returns product of the constant and the integer represented as polynomial. + * Returns product of the constant and the integer represented as a polynomial. * * The operation is equivalent to sum of [other] copies of [this]. */ public override operator fun P.times(other: Int): P = polynomialRing { this@times * other } /** - * Returns sum of the integer represented as polynomial and the constant. + * 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]. */ public override operator fun Int.plus(other: P): P = polynomialRing { this@plus + other } /** - * Returns difference between the integer represented as polynomial and the constant. + * 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]. */ public override operator fun Int.minus(other: P): P = polynomialRing { this@minus - other } /** - * Returns product of the integer represented as polynomial and the constant. + * Returns product of the integer represented as a polynomial and the constant. * * The operation is equivalent to sum of [this] copies of [other]. */ @@ -697,28 +708,28 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< public override val constantOne: C get() = polynomialRing.constantOne /** - * Returns sum of the constant represented as polynomial and the polynomial. + * Returns sum of the constant represented as a polynomial and the polynomial. */ public override operator fun C.plus(other: P): P = polynomialRing { this@plus + other } /** - * Returns difference between the constant represented as polynomial and the polynomial. + * Returns difference between the constant represented as a polynomial and the polynomial. */ public override operator fun C.minus(other: P): P = polynomialRing { this@minus - other } /** - * Returns product of the constant represented as polynomial and the polynomial. + * Returns product of the constant represented as a polynomial and the polynomial. */ public override operator fun C.times(other: P): P = polynomialRing { this@times * other } /** - * Returns sum of the constant represented as polynomial and the polynomial. + * Returns sum of the constant represented as a polynomial and the polynomial. */ public override operator fun P.plus(other: C): P = polynomialRing { this@plus + other } /** - * Returns difference between the constant represented as polynomial and the polynomial. + * Returns difference between the constant represented as a polynomial and the polynomial. */ public override operator fun P.minus(other: C): P = polynomialRing { this@minus - other } /** - * Returns product of the constant represented as polynomial and the polynomial. + * Returns product of the constant represented as a polynomial and the polynomial. */ public override operator fun P.times(other: C): P = polynomialRing { this@times * other } @@ -774,7 +785,8 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< /** * 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 + * [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. @@ -786,10 +798,14 @@ public abstract class PolynomialSpaceOfFractions< P: Polynomial, R: RationalFunction, > : RationalFunctionalSpace { + + /** + * 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 rational function. + * 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]. */ @@ -799,7 +815,7 @@ public abstract class PolynomialSpaceOfFractions< denominator ) /** - * Returns difference between the rational function and the integer represented as rational function. + * 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]. */ @@ -809,7 +825,7 @@ public abstract class PolynomialSpaceOfFractions< denominator ) /** - * Returns product of the rational function and the integer represented as rational function. + * 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]. */ @@ -826,7 +842,7 @@ public abstract class PolynomialSpaceOfFractions< ) /** - * Returns sum of the integer represented as rational function and the rational function. + * 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]. */ @@ -836,7 +852,7 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) /** - * Returns difference between the integer represented as rational function and the rational function. + * 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]. */ @@ -846,7 +862,7 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) /** - * Returns product of the integer represented as rational function and the rational function. + * 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]. */ @@ -873,7 +889,7 @@ public abstract class PolynomialSpaceOfFractions< public override operator fun P.div(other: P): R = constructRationalFunction(this, other) /** - * Returns sum of the constant represented as rational function and the rational function. + * Returns sum of the constant represented as a rational function and the rational function. */ public override operator fun C.plus(other: R): R = constructRationalFunction( @@ -881,7 +897,7 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) /** - * Returns difference between the constant represented as polynomial and the rational function. + * Returns difference between the constant represented as a polynomial and the rational function. */ public override operator fun C.minus(other: R): R = constructRationalFunction( @@ -889,7 +905,7 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) /** - * Returns product of the constant represented as polynomial and the rational function. + * Returns product of the constant represented as a polynomial and the rational function. */ public override operator fun C.times(other: R): R = constructRationalFunction( @@ -904,7 +920,7 @@ public abstract class PolynomialSpaceOfFractions< ) /** - * Returns sum of the constant represented as rational function and the rational function. + * Returns sum of the constant represented as a rational function and the rational function. */ public override operator fun R.plus(other: C): R = constructRationalFunction( @@ -912,7 +928,7 @@ public abstract class PolynomialSpaceOfFractions< denominator ) /** - * Returns difference between the constant represented as rational function and the rational function. + * Returns difference between the constant represented as a rational function and the rational function. */ public override operator fun R.minus(other: C): R = constructRationalFunction( @@ -920,7 +936,7 @@ public abstract class PolynomialSpaceOfFractions< denominator ) /** - * Returns product of the constant represented as rational function and the rational function. + * Returns product of the constant represented as a rational function and the rational function. */ public override operator fun R.times(other: C): R = constructRationalFunction( @@ -940,7 +956,7 @@ public abstract class PolynomialSpaceOfFractions< public override fun number(value: C): R = constructRationalFunction(polynomialNumber(value)) /** - * Returns sum of the polynomial represented as rational function and the rational function. + * Returns sum of the polynomial represented as a rational function and the rational function. */ public override operator fun P.plus(other: R): R = constructRationalFunction( @@ -948,7 +964,7 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) /** - * Returns difference between the polynomial represented as polynomial and the rational function. + * Returns difference between the polynomial represented as a polynomial and the rational function. */ public override operator fun P.minus(other: R): R = constructRationalFunction( @@ -956,7 +972,7 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) /** - * Returns product of the polynomial represented as polynomial and the rational function. + * Returns product of the polynomial represented as a polynomial and the rational function. */ public override operator fun P.times(other: R): R = constructRationalFunction( @@ -971,7 +987,7 @@ public abstract class PolynomialSpaceOfFractions< ) /** - * Returns sum of the polynomial represented as rational function and the rational function. + * Returns sum of the polynomial represented as a rational function and the rational function. */ public override operator fun R.plus(other: P): R = constructRationalFunction( @@ -979,7 +995,7 @@ public abstract class PolynomialSpaceOfFractions< denominator ) /** - * Returns difference between the polynomial represented as rational function and the rational function. + * Returns difference between the polynomial represented as a rational function and the rational function. */ public override operator fun R.minus(other: P): R = constructRationalFunction( @@ -987,7 +1003,7 @@ public abstract class PolynomialSpaceOfFractions< denominator ) /** - * Returns product of the polynomial represented as rational function and the rational function. + * Returns product of the polynomial represented as a rational function and the rational function. */ public override operator fun R.times(other: P): R = constructRationalFunction( @@ -1052,6 +1068,15 @@ public abstract class PolynomialSpaceOfFractions< public override val one: R get() = 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 MultivariateRationalFunctionalSpace< C, @@ -1059,70 +1084,175 @@ public interface MultivariateRationalFunctionalSpace< P: Polynomial, R: RationalFunction >: RationalFunctionalSpace { + /** + * Returns sum of the variable represented as a monic monomial and the integer represented as a constant polynomial. + */ @JvmName("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") 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") 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") 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") 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") public operator fun Int.times(other: V): P - @JvmName("plusConstantVariable") - public operator fun C.plus(other: V): P - @JvmName("minusConstantVariable") - public operator fun C.minus(other: V): P - @JvmName("timesConstantVariable") - public operator fun C.times(other: V): P - + /** + * Returns sum of the variable represented as a monic monomial and the constant represented as a constant polynomial. + */ @JvmName("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") 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") 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") + 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") + 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") + 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. + */ + public fun polynomialNumber(variable: V): P = +variable + /** + * Represents the variable as a monic monomial. + */ + public fun V.asPolynomial(): P = polynomialNumber(this) + + /** + * Represents the [variable] as a rational function. + */ + public fun number(variable: V): R = number(polynomialNumber(variable)) + /** + * Represents the variable as a rational function. + */ + 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 @@ -1161,22 +1291,17 @@ public interface MultivariateRationalFunctionalSpace< public val R.countOfVariables: Int get() = variables.size } -public interface MultivariateRationalFunctionalSpaceOverRing< - C, - V, - P: Polynomial, - R: RationalFunction, - A: Ring - > : RationalFunctionalSpaceOverRing, MultivariateRationalFunctionalSpace - -public interface MultivariateRationalFunctionalSpaceOverPolynomialSpace< - C, - V, - P: Polynomial, - R: RationalFunction, - AP: PolynomialSpace, - > : RationalFunctionalSpaceOverPolynomialSpace, MultivariateRationalFunctionalSpace - +/** + * 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 MultivariateRationalFunctionalSpaceOverMultivariatePolynomialSpace< C, @@ -1184,57 +1309,135 @@ public interface MultivariateRationalFunctionalSpaceOverMultivariatePolynomialSp P: Polynomial, R: RationalFunction, AP: MultivariatePolynomialSpace, - > : MultivariateRationalFunctionalSpaceOverPolynomialSpace { + > : RationalFunctionalSpaceOverPolynomialSpace, MultivariateRationalFunctionalSpace { + /** + * 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 } - @JvmName("plusConstantVariable") - public override operator fun C.plus(other: V): P = polynomialRing { this@plus + other } - @JvmName("minusConstantVariable") - public override operator fun C.minus(other: V): P = polynomialRing { this@minus - other } - @JvmName("timesConstantVariable") - public override operator fun C.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. + */ + public override fun polynomialNumber(variable: V): P = polynomialRing { number(variable) } + /** + * Represents the variable as a monic monomial. + */ + 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 } @@ -1264,6 +1467,16 @@ public interface MultivariateRationalFunctionalSpaceOverMultivariatePolynomialSp 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, @@ -1271,18 +1484,27 @@ public abstract class MultivariatePolynomialSpaceOfFractions< P: Polynomial, R: RationalFunction, > : MultivariateRationalFunctionalSpace, 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( @@ -1290,18 +1512,27 @@ public abstract class MultivariatePolynomialSpaceOfFractions< 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. + */ @JvmName("timesRationalVariable") public override operator fun R.times(other: V): R = constructRationalFunction( -- 2.34.1 From 569e01fce13f890e8c938d90ac4285e99f3b3e93 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 12 Jun 2022 15:16:40 +0300 Subject: [PATCH 080/275] Migration to kotlin 1.7 --- build.gradle.kts | 2 +- buildSrc/build.gradle.kts | 13 +++---- buildSrc/gradle.properties | 7 ---- buildSrc/settings.gradle.kts | 14 ++++++-- .../kmath/ejml/codegen/ejmlCodegen.kt | 4 ++- gradle.properties | 5 ++- kmath-ast/build.gradle.kts | 2 +- kmath-core/build.gradle.kts | 4 +-- .../space/kscience/kmath/nd/AlgebraND.kt | 19 ---------- .../kscience/kmath/nd/BufferAlgebraND.kt | 2 +- .../kotlin/space/kscience/kmath/nd/Shape.kt | 35 +++++++++++++++++++ .../space/kscience/kmath/nd/ShapeIndexer.kt | 14 +++++--- .../space/kscience/kmath/nd/StructureND.kt | 4 +-- .../kscience/kmath/nd/VirtualStructureND.kt | 18 ++++++++-- .../space/kscience/kmath/nd/operationsND.kt | 32 +++++++++++++++++ .../kscience/kmath/nd/NdOperationsTest.kt | 28 +++++++++++++++ .../space/kscience/kmath/ejml/_generated.kt | 16 ++++++--- .../kscience/kmath/ejml/EjmlMatrixTest.kt | 6 ++-- kmath-histograms/build.gradle.kts | 8 ++--- .../kmath/histogram/TreeHistogramTest.kt | 2 ++ kmath-memory/build.gradle.kts | 3 +- kmath-optimization/build.gradle.kts | 5 +-- kmath-stat/build.gradle.kts | 5 +-- .../space/kscience/kmath/stat/Sampler.kt | 2 ++ .../space/kscience/kmath/stat/MCScopeTest.kt | 2 +- .../kscience/kmath/viktor/ViktorFieldOpsND.kt | 1 + settings.gradle.kts | 20 ++++++++++- 27 files changed, 200 insertions(+), 73 deletions(-) delete mode 100644 buildSrc/gradle.properties create 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/operationsND.kt create mode 100644 kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/NdOperationsTest.kt diff --git a/build.gradle.kts b/build.gradle.kts index 9fa012fb2..ab136bfbc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,7 +11,7 @@ allprojects { } group = "space.kscience" - version = "0.3.1" + version = "0.3.1-dev-1" } subprojects { diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index dcb39d448..20611e92d 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -1,8 +1,8 @@ plugins { - kotlin("jvm") version "1.7.0-RC" + kotlin("jvm") version "1.7.0" `kotlin-dsl` `version-catalog` - alias(miptNpmLibs.plugins.kotlin.plugin.serialization) + alias(npmlibs.plugins.kotlin.plugin.serialization) } java.targetCompatibility = JavaVersion.VERSION_11 @@ -14,17 +14,18 @@ repositories { gradlePluginPortal() } -val toolsVersion: String by extra -val kotlinVersion = miptNpmLibs.versions.kotlin.asProvider().get() -val benchmarksVersion = miptNpmLibs.versions.kotlinx.benchmark.get() +val toolsVersion = npmlibs.versions.tools.get() +val kotlinVersion = npmlibs.versions.kotlin.asProvider().get() +val benchmarksVersion = npmlibs.versions.kotlinx.benchmark.get() dependencies { api("ru.mipt.npm:gradle-tools:$toolsVersion") + api(npmlibs.atomicfu.gradle) //plugins form benchmarks api("org.jetbrains.kotlinx:kotlinx-benchmark-plugin:$benchmarksVersion") api("org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion") //to be used inside build-script only - implementation(miptNpmLibs.kotlinx.serialization.json) + implementation(npmlibs.kotlinx.serialization.json) } kotlin.sourceSets.all { diff --git a/buildSrc/gradle.properties b/buildSrc/gradle.properties deleted file mode 100644 index 751caec36..000000000 --- a/buildSrc/gradle.properties +++ /dev/null @@ -1,7 +0,0 @@ -# -# Copyright 2018-2021 KMath contributors. -# Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. -# - -kotlin.code.style=official -toolsVersion=0.11.5-kotlin-1.7.0-RC diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts index 7c1df133d..bce265510 100644 --- a/buildSrc/settings.gradle.kts +++ b/buildSrc/settings.gradle.kts @@ -6,7 +6,17 @@ enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") dependencyResolutionManagement { - val toolsVersion: String by extra + val projectProperties = java.util.Properties() + file("../gradle.properties").inputStream().use { + projectProperties.load(it) + } + + projectProperties.forEach { key, value -> + extra.set(key.toString(), value) + } + + + val toolsVersion: String = projectProperties["toolsVersion"].toString() repositories { mavenLocal() @@ -16,7 +26,7 @@ dependencyResolutionManagement { } versionCatalogs { - create("miptNpmLibs") { + create("npmlibs") { from("ru.mipt.npm:version-catalog:$toolsVersion") } } diff --git a/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt b/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt index 7f8cb35b3..7c23d8ea0 100644 --- a/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt +++ b/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt @@ -319,7 +319,9 @@ public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra}, } else -> null - }?.let(type::cast) + }?.let{ + type.cast(it) + } } /** diff --git a/gradle.properties b/gradle.properties index 4923364d8..9cdd7801c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,10 @@ kotlin.code.style=official kotlin.jupyter.add.scanner=false kotlin.mpp.stability.nowarn=true kotlin.native.ignoreDisabledTargets=true -#kotlin.incremental.js.ir=true +//kotlin.incremental.js.ir=true org.gradle.configureondemand=true org.gradle.parallel=true +org.gradle.jvmargs=-Xmx4096m + +toolsVersion=0.11.6-kotlin-1.7.0 diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index 15b1d0900..0dd625ef1 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -57,7 +57,7 @@ tasks.dokkaHtml { if (System.getProperty("space.kscience.kmath.ast.dump.generated.classes") == "1") tasks.jvmTest { - jvmArgs = (jvmArgs ?: emptyList()) + listOf("-Dspace.kscience.kmath.ast.dump.generated.classes=1") + jvmArgs("-Dspace.kscience.kmath.ast.dump.generated.classes=1") } readme { diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index 4a35a54fb..052924ce8 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -1,8 +1,6 @@ plugins { - kotlin("multiplatform") - id("ru.mipt.npm.gradle.common") + id("ru.mipt.npm.gradle.mpp") id("ru.mipt.npm.gradle.native") -// id("com.xcporter.metaview") version "0.0.5" } kotlin.sourceSets { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt index a9712e870..ad291cf7f 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 @@ -10,25 +10,6 @@ import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* import kotlin.reflect.KClass -/** - * An exception is thrown when the expected and actual shape of NDArray differ. - * - * @property expected the expected shape. - * @property actual the actual shape. - */ -public class ShapeMismatchException(public val expected: IntArray, public val actual: IntArray) : - RuntimeException("Shape ${actual.contentToString()} doesn't fit in expected shape ${expected.contentToString()}.") - -public typealias Shape = IntArray - -public fun Shape(shapeFirst: Int, vararg shapeRest: Int): Shape = intArrayOf(shapeFirst, *shapeRest) - -public interface WithShape { - public val shape: Shape - - public val indices: ShapeIndexer get() = DefaultStrides(shape) -} - /** * The base interface for all ND-algebra implementations. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt index b09344d12..68e8ebe90 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 @@ -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) -> ShapeIndexer = ::Strides } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Shape.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Shape.kt new file mode 100644 index 000000000..d682d5e69 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Shape.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.nd + +/** + * An exception is thrown when the expected and actual shape of NDArray differ. + * + * @property expected the expected shape. + * @property actual the actual shape. + */ +public class ShapeMismatchException(public val expected: IntArray, public val actual: IntArray) : + RuntimeException("Shape ${actual.contentToString()} doesn't fit in expected shape ${expected.contentToString()}.") + +public class IndexOutOfShapeException(public val shape: Shape, public val index: IntArray) : + RuntimeException("Index ${index.contentToString()} is out of shape ${shape.contentToString()}") + +public typealias Shape = IntArray + +public fun Shape(shapeFirst: Int, vararg shapeRest: Int): Shape = intArrayOf(shapeFirst, *shapeRest) + +public interface WithShape { + public val shape: Shape + + public val indices: ShapeIndexer get() = DefaultStrides(shape) +} + +internal fun requireIndexInShape(index: IntArray, shape: Shape) { + if (index.size != shape.size) throw IndexOutOfShapeException(index, shape) + shape.forEachIndexed { axis, axisShape -> + if (index[axis] !in 0 until axisShape) throw IndexOutOfShapeException(index, shape) + } +} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndexer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndexer.kt index c6ff79587..29701425f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndexer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndexer.kt @@ -10,7 +10,7 @@ import kotlin.native.concurrent.ThreadLocal /** * A converter from linear index to multivariate index */ -public interface ShapeIndexer: Iterable{ +public interface ShapeIndexer : Iterable { public val shape: Shape /** @@ -44,7 +44,7 @@ public interface ShapeIndexer: Iterable{ /** * Linear transformation of indexes */ -public abstract class Strides: ShapeIndexer { +public abstract class Strides : ShapeIndexer { /** * Array strides */ @@ -66,7 +66,7 @@ public abstract class Strides: ShapeIndexer { /** * Simple implementation of [Strides]. */ -public class DefaultStrides private constructor(override val shape: IntArray) : Strides() { +public class DefaultStrides(override val shape: IntArray) : Strides() { override val linearSize: Int get() = strides[shape.size] /** @@ -112,10 +112,16 @@ public class DefaultStrides private constructor(override val shape: IntArray) : /** * Cached builder for default strides */ + @Deprecated("Replace by Strides(shape)") public operator fun invoke(shape: IntArray): Strides = defaultStridesCache.getOrPut(shape) { DefaultStrides(shape) } } } @ThreadLocal -private val defaultStridesCache = HashMap() \ No newline at end of file +private val defaultStridesCache = HashMap() + +/** + * Cached builder for default strides + */ +public fun Strides(shape: IntArray): Strides = defaultStridesCache.getOrPut(shape) { DefaultStrides(shape) } \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt index d948cf36f..e934c6370 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 @@ -101,8 +101,8 @@ public interface StructureND : Featured, WithShape { val bufferRepr: String = when (structure.shape.size) { 1 -> (0 until structure.shape[0]).map { structure[it] } .joinToString(prefix = "[", postfix = "]", separator = ", ") - 2 -> (0 until structure.shape[0]).joinToString(prefix = "[", postfix = "]", separator = ", ") { i -> - (0 until structure.shape[1]).joinToString(prefix = "[", postfix = "]", separator = ", ") { j -> + 2 -> (0 until structure.shape[0]).joinToString(prefix = "[\n", postfix = "\n]", separator = ",\n") { i -> + (0 until structure.shape[1]).joinToString(prefix = " [", postfix = "]", separator = ", ") { j -> structure[i, j].toString() } } 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 799d14b3d..7e86ea73d 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,26 @@ package space.kscience.kmath.nd +import space.kscience.kmath.misc.UnstableKMathAPI + public open class VirtualStructureND( override val shape: Shape, public val producer: (IntArray) -> T, ) : StructureND { override fun get(index: IntArray): T { - require(check that index is in the shape boundaries) + requireIndexInShape(index, shape) return producer(index) } -} \ No newline at end of file +} + +@UnstableKMathAPI +public class VirtualDoubleStructureND( + shape: Shape, + producer: (IntArray) -> Double, +) : VirtualStructureND(shape, producer) + +@UnstableKMathAPI +public class VirtualIntStructureND( + shape: Shape, + producer: (IntArray) -> Int, +) : VirtualStructureND(shape, producer) \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/operationsND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/operationsND.kt new file mode 100644 index 000000000..c9624dc4e --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/operationsND.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.nd + +public fun StructureND.roll(axis: Int, step: Int = 1): StructureND { + require(axis in shape.indices) { "Axis $axis is outside of shape dimensions: [0, ${shape.size})" } + return VirtualStructureND(shape) { index -> + val newIndex: IntArray = IntArray(index.size) { indexAxis -> + if (indexAxis == axis) { + (index[indexAxis] + step).mod(shape[indexAxis]) + } else { + index[indexAxis] + } + } + get(newIndex) + } +} + +public fun StructureND.roll(pair: Pair, vararg others: Pair): StructureND { + val axisMap: Map = mapOf(pair, *others) + require(axisMap.keys.all { it in shape.indices }) { "Some of axes ${axisMap.keys} is outside of shape dimensions: [0, ${shape.size})" } + return VirtualStructureND(shape) { index -> + val newIndex: IntArray = IntArray(index.size) { indexAxis -> + val offset = axisMap[indexAxis] ?: 0 + (index[indexAxis] + offset).mod(shape[indexAxis]) + } + get(newIndex) + } +} \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/NdOperationsTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/NdOperationsTest.kt new file mode 100644 index 000000000..25b062b44 --- /dev/null +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/NdOperationsTest.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.nd + +import space.kscience.kmath.operations.DoubleField +import kotlin.test.Test +import kotlin.test.assertEquals + +class NdOperationsTest { + @Test + fun roll() { + val structure = DoubleField.ndAlgebra.structureND(5, 5) { index -> + index.sumOf { it.toDouble() } + } + + println(StructureND.toString(structure)) + + val rolled = structure.roll(0,-1) + + println(StructureND.toString(rolled)) + + assertEquals(4.0, rolled[0, 0]) + } + +} \ No newline at end of file diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt index dce739dc2..aac327a84 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt @@ -271,7 +271,9 @@ public object EjmlLinearSpaceDDRM : EjmlLinearSpace null - }?.let(type::cast) + }?.let{ + type.cast(it) + } } /** @@ -505,7 +507,9 @@ public object EjmlLinearSpaceFDRM : EjmlLinearSpace null - }?.let(type::cast) + }?.let{ + type.cast(it) + } } /** @@ -734,7 +738,9 @@ public object EjmlLinearSpaceDSCC : EjmlLinearSpace null - }?.let(type::cast) + }?.let{ + type.cast(it) + } } /** @@ -963,7 +969,9 @@ public object EjmlLinearSpaceFSCC : EjmlLinearSpace null - }?.let(type::cast) + }?.let{ + type.cast(it) + } } /** diff --git a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt index 209bb5b27..af6284e5e 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 @@ -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(PerformancePitfall::class) + package space.kscience.kmath.ejml import org.ejml.data.DMatrixRMaj @@ -18,11 +20,11 @@ import kotlin.random.Random import kotlin.random.asJavaRandom import kotlin.test.* -@OptIn(PerformancePitfall::class) -fun assertMatrixEquals(expected: StructureND, actual: StructureND) { +internal fun assertMatrixEquals(expected: StructureND, actual: StructureND) { assertTrue { StructureND.contentEquals(expected, actual) } } +@OptIn(UnstableKMathAPI::class) internal class EjmlMatrixTest { private val random = Random(0) diff --git a/kmath-histograms/build.gradle.kts b/kmath-histograms/build.gradle.kts index 51271bb0a..786086c9f 100644 --- a/kmath-histograms/build.gradle.kts +++ b/kmath-histograms/build.gradle.kts @@ -1,17 +1,15 @@ plugins { - kotlin("multiplatform") - id("ru.mipt.npm.gradle.common") + id("ru.mipt.npm.gradle.mpp") id("ru.mipt.npm.gradle.native") } -kscience { - useAtomic() -} +//apply(plugin = "kotlinx-atomicfu") kotlin.sourceSets { commonMain { dependencies { api(project(":kmath-core")) + api(npmlibs.atomicfu) } } commonTest { diff --git a/kmath-histograms/src/jvmTest/kotlin/space/kscience/kmath/histogram/TreeHistogramTest.kt b/kmath-histograms/src/jvmTest/kotlin/space/kscience/kmath/histogram/TreeHistogramTest.kt index c4eeb53cc..2c56a88a7 100644 --- a/kmath-histograms/src/jvmTest/kotlin/space/kscience/kmath/histogram/TreeHistogramTest.kt +++ b/kmath-histograms/src/jvmTest/kotlin/space/kscience/kmath/histogram/TreeHistogramTest.kt @@ -6,12 +6,14 @@ package space.kscience.kmath.histogram import org.junit.jupiter.api.Test +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.real.step import kotlin.random.Random import kotlin.test.assertEquals import kotlin.test.assertTrue +@OptIn(UnstableKMathAPI::class) class TreeHistogramTest { @Test diff --git a/kmath-memory/build.gradle.kts b/kmath-memory/build.gradle.kts index 4478e5b80..2bd6dd723 100644 --- a/kmath-memory/build.gradle.kts +++ b/kmath-memory/build.gradle.kts @@ -1,6 +1,5 @@ plugins { - kotlin("multiplatform") - id("ru.mipt.npm.gradle.common") + id("ru.mipt.npm.gradle.mpp") id("ru.mipt.npm.gradle.native") } diff --git a/kmath-optimization/build.gradle.kts b/kmath-optimization/build.gradle.kts index b920b9267..2e5bf6005 100644 --- a/kmath-optimization/build.gradle.kts +++ b/kmath-optimization/build.gradle.kts @@ -3,10 +3,6 @@ plugins { id("ru.mipt.npm.gradle.native") } -kscience { - useAtomic() -} - kotlin.sourceSets { all { languageSettings.optIn("space.kscience.kmath.misc.UnstableKMathAPI") @@ -15,6 +11,7 @@ kotlin.sourceSets { commonMain { dependencies { api(project(":kmath-coroutines")) + api(npmlibs.atomicfu) } } } diff --git a/kmath-stat/build.gradle.kts b/kmath-stat/build.gradle.kts index 41a1666f8..b458135b3 100644 --- a/kmath-stat/build.gradle.kts +++ b/kmath-stat/build.gradle.kts @@ -3,14 +3,11 @@ plugins { id("ru.mipt.npm.gradle.native") } -kscience { - useAtomic() -} - kotlin.sourceSets { commonMain { dependencies { api(project(":kmath-coroutines")) + implementation(npmlibs.atomicfu) } } diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt index c96ecdc8c..a88f3e437 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt @@ -8,6 +8,7 @@ package space.kscience.kmath.stat import kotlinx.coroutines.flow.first import space.kscience.kmath.chains.Chain import space.kscience.kmath.chains.combine +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.DoubleBuffer @@ -30,6 +31,7 @@ public fun interface Sampler { /** * Sample a bunch of values */ +@OptIn(UnstableKMathAPI::class) public fun Sampler.sampleBuffer( generator: RandomGenerator, size: Int, diff --git a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/MCScopeTest.kt b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/MCScopeTest.kt index 075d7f3e5..cca645809 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 @@ -66,7 +66,7 @@ class MCScopeTest { } - @OptIn(ObsoleteCoroutinesApi::class) + @OptIn(DelicateCoroutinesApi::class) fun compareResult(test: ATest) { val res1 = runBlocking(Dispatchers.Default) { test() } val res2 = runBlocking(newSingleThreadContext("test")) { test() } diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorFieldOpsND.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorFieldOpsND.kt index 1d4d6cebd..cecbc35b8 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 @@ -117,6 +117,7 @@ public open class ViktorFieldOpsND : public val DoubleField.viktorAlgebra: ViktorFieldOpsND get() = ViktorFieldOpsND +@OptIn(UnstableKMathAPI::class) public open class ViktorFieldND( override val shape: Shape, ) : ViktorFieldOpsND(), FieldND, NumbersAddOps> { diff --git a/settings.gradle.kts b/settings.gradle.kts index b3c275810..b14c594b4 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,6 +1,24 @@ rootProject.name = "kmath" enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") + +dependencyResolutionManagement { + val toolsVersion: String by extra + + repositories { + mavenLocal() + maven("https://repo.kotlin.link") + mavenCentral() + gradlePluginPortal() + } + + versionCatalogs { + create("npmlibs") { + from("ru.mipt.npm:version-catalog:$toolsVersion") + } + } +} + include( ":kmath-memory", ":kmath-complex", @@ -27,4 +45,4 @@ include( ":kmath-jafama", ":examples", ":benchmarks", -) +) \ No newline at end of file -- 2.34.1 From e1276b684f5b4220b01842f325a0407d14a1415f Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 12 Jun 2022 15:19:59 +0300 Subject: [PATCH 081/275] Update better-parse --- kmath-ast/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index 0dd625ef1..f49c2767a 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -24,7 +24,7 @@ kotlin.sourceSets { commonMain { dependencies { - api("com.github.h0tk3y.betterParse:better-parse:0.4.2") + api("com.github.h0tk3y.betterParse:better-parse:0.4.4") api(project(":kmath-core")) } } -- 2.34.1 From fabad733f4cb9436fd3dd34ea0dbb3871e0348ea Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 12 Jun 2022 15:30:10 +0300 Subject: [PATCH 082/275] Fix binaryen module creation --- .../kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt index aacb62f36..878919d8d 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt @@ -71,7 +71,7 @@ internal sealed class WasmBuilder>( protected open fun visitBinary(mst: TypedMst.Binary): ExpressionRef = error("Binary operation ${mst.operation} not defined in $this") - protected open fun createModule(): BinaryenModule = js("new \$module\$binaryen.Module()") + protected open fun createModule(): BinaryenModule = space.kscience.kmath.internal.binaryen.Module() protected fun visit(node: TypedMst): ExpressionRef = when (node) { is TypedMst.Constant -> visitNumber( -- 2.34.1 From 3a6aa1432094c6803ac026593e3035c14a51111d Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sun, 12 Jun 2022 22:52:08 +0300 Subject: [PATCH 083/275] Cleaned up ListPolynomials and ListRationalFunctions: - Added/updated docs. - Fully (but in a simple way) implemented invocation, substitution, functional representation, derivatives and antiderivatives. Optimized reimplementation is in progress. - Upgraded `PolynomialSpaceOfFractions` by adding a bit of laziness. - Other little things... --- .../kmath/functions/ListPolynomial.kt | 80 ++++-- .../kmath/functions/ListRationalFunction.kt | 159 +++++++---- .../kscience/kmath/functions/Polynomial.kt | 2 + .../kmath/functions/RationalFunction.kt | 10 +- .../kmath/functions/listPolynomialUtil.kt | 233 --------------- .../kscience/kmath/functions/listUtil.kt | 268 ++++++++++++++++++ ...alFunctionUtil.kt => listUtilOptimized.kt} | 129 +++++---- .../space/kscience/kmath/functions/misc.kt | 13 + .../kmath/functions/ListPolynomialUtilTest.kt | 2 + .../kscience/kmath/test/misc/Rational.kt | 135 +++++++++ .../space/kscience/kmath/test/misc/misc.kt | 11 + 11 files changed, 667 insertions(+), 375 deletions(-) delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt rename kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/{listRationalFunctionUtil.kt => listUtilOptimized.kt} (72%) create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt index 585da95ea..fce179fc8 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt @@ -8,23 +8,19 @@ 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.contracts.InvocationKind -import kotlin.contracts.contract -import kotlin.experimental.ExperimentalTypeInference -import kotlin.jvm.JvmName import kotlin.math.max import kotlin.math.min /** - * Polynomial model without fixation on specific context they are applied to. + * Represents univariate polynomial that stores its coefficients in a [List]. * * @param coefficients constant is the leftmost coefficient. */ public data class ListPolynomial( /** - * List that collects coefficients of the polynomial. Every monomial `a x^d` is represented as a coefficients - * `a` placed into the list with index `d`. For example coefficients of polynomial `5 x^2 - 6` can be represented as + * 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 + @@ -42,26 +38,28 @@ public data class ListPolynomial( * 0, // 0 x^4 * ) * ``` - * It is recommended not to put extra zeros at end of the list (as for `0x^3` and `0x^4` in the example), but is not - * prohibited. + * 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. */ public val coefficients: List ) : Polynomial { - override fun toString(): String = "Polynomial$coefficients" + override fun toString(): String = "ListPolynomial$coefficients" } /** - * Space of univariate polynomials constructed over ring. + * Arithmetic context for univariate polynomials with coefficients stored as a [List] constructed with the given [ring] + * of constants. * - * @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 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 polynomial. + * 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]. */ @@ -79,7 +77,7 @@ public open class ListPolynomialSpace>( } ) /** - * Returns difference between the polynomial and the integer represented as polynomial. + * 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]. */ @@ -97,7 +95,7 @@ public open class ListPolynomialSpace>( } ) /** - * Returns product of the polynomial and the integer represented as polynomial. + * Returns product of the polynomial and the integer represented as a polynomial. * * The operation is equivalent to sum of [other] copies of [this]. */ @@ -112,7 +110,7 @@ public open class ListPolynomialSpace>( ) /** - * Returns sum of the integer represented as polynomial and the polynomial. + * 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]. */ @@ -130,7 +128,7 @@ public open class ListPolynomialSpace>( } ) /** - * Returns difference between the integer represented as polynomial and the polynomial. + * 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]. */ @@ -150,7 +148,7 @@ public open class ListPolynomialSpace>( } ) /** - * Returns product of the integer represented as polynomial and the polynomial. + * Returns product of the integer represented as a polynomial and the polynomial. * * The operation is equivalent to sum of [this] copies of [other]. */ @@ -170,7 +168,7 @@ public open class ListPolynomialSpace>( public override fun number(value: Int): ListPolynomial = number(constantNumber(value)) /** - * Returns sum of the constant represented as polynomial and the polynomial. + * Returns sum of the constant represented as a polynomial and the polynomial. */ public override operator fun C.plus(other: ListPolynomial): ListPolynomial = with(other.coefficients) { @@ -186,7 +184,7 @@ public open class ListPolynomialSpace>( ) } /** - * Returns difference between the constant represented as polynomial and the polynomial. + * Returns difference between the constant represented as a polynomial and the polynomial. */ public override operator fun C.minus(other: ListPolynomial): ListPolynomial = with(other.coefficients) { @@ -204,7 +202,7 @@ public open class ListPolynomialSpace>( ) } /** - * Returns product of the constant represented as polynomial and the polynomial. + * Returns product of the constant represented as a polynomial and the polynomial. */ public override operator fun C.times(other: ListPolynomial): ListPolynomial = ListPolynomial( @@ -216,7 +214,7 @@ public open class ListPolynomialSpace>( ) /** - * Returns sum of the constant represented as polynomial and the polynomial. + * Returns sum of the constant represented as a polynomial and the polynomial. */ public override operator fun ListPolynomial.plus(other: C): ListPolynomial = with(coefficients) { @@ -232,7 +230,7 @@ public open class ListPolynomialSpace>( ) } /** - * Returns difference between the constant represented as polynomial and the polynomial. + * Returns difference between the constant represented as a polynomial and the polynomial. */ public override operator fun ListPolynomial.minus(other: C): ListPolynomial = with(coefficients) { @@ -248,7 +246,7 @@ public open class ListPolynomialSpace>( ) } /** - * Returns product of the constant represented as polynomial and the polynomial. + * Returns product of the constant represented as a polynomial and the polynomial. */ public override operator fun ListPolynomial.times(other: C): ListPolynomial = ListPolynomial( @@ -262,7 +260,7 @@ public open class ListPolynomialSpace>( /** * Converts the constant [value] to polynomial. */ - public override fun number(value: C): ListPolynomial = ListPolynomial(value) + public override fun number(value: C): ListPolynomial = ListPolynomial(listOf(value)) /** * Returns negation of the polynomial. @@ -321,9 +319,9 @@ public open class ListPolynomialSpace>( */ override val zero: ListPolynomial = ListPolynomial(emptyList()) /** - * Instance of unit constant (unit of the underlying ring). + * Instance of unit polynomial (unit of the polynomial ring). */ - override val one: ListPolynomial = ListPolynomial(listOf(constantOne)) + 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 @@ -331,23 +329,43 @@ public open class ListPolynomialSpace>( */ 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. + */ @Suppress("NOTHING_TO_INLINE") public inline fun ListPolynomial.substitute(argument: C): C = this.substitute(ring, argument) + /** + * Substitutes provided polynomial [argument] into [this] polynomial. + */ @Suppress("NOTHING_TO_INLINE") public inline fun ListPolynomial.substitute(argument: ListPolynomial): ListPolynomial = this.substitute(ring, argument) + /** + * Represent [this] polynomial as a regular context-less function. + */ @Suppress("NOTHING_TO_INLINE") public inline fun ListPolynomial.asFunction(): (C) -> C = { this.substitute(ring, it) } + /** + * Represent [this] polynomial as a regular context-less function. + */ @Suppress("NOTHING_TO_INLINE") - public inline fun ListPolynomial.asFunctionOnConstants(): (C) -> C = { this.substitute(ring, it) } + public inline fun ListPolynomial.asFunctionOfConstant(): (C) -> C = { this.substitute(ring, it) } + /** + * Represent [this] polynomial as a regular context-less function. + */ @Suppress("NOTHING_TO_INLINE") - public inline fun ListPolynomial.asFunctionOnPolynomials(): (ListPolynomial) -> ListPolynomial = { this.substitute(ring, it) } + public inline fun ListPolynomial.asFunctionOfPolynomial(): (ListPolynomial) -> ListPolynomial = { this.substitute(ring, it) } /** - * Evaluates the polynomial for the given value [argument]. + * Evaluates value of [this] polynomial on provided [argument]. */ @Suppress("NOTHING_TO_INLINE") public inline operator fun ListPolynomial.invoke(argument: C): C = this.substitute(ring, argument) + /** + * Evaluates value of [this] polynomial on provided [argument]. + */ @Suppress("NOTHING_TO_INLINE") public inline operator fun ListPolynomial.invoke(argument: ListPolynomial): ListPolynomial = this.substitute(ring, argument) } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt index 7b6c23ac3..45ea99fb0 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt @@ -8,13 +8,23 @@ package space.kscience.kmath.functions import space.kscience.kmath.operations.Ring +/** + * Represents 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 = "RationalFunction${numerator.coefficients}/${denominator.coefficients}" + 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, ) : @@ -30,7 +40,13 @@ public class ListRationalFunctionSpace> ( 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) @@ -43,63 +59,88 @@ public class ListRationalFunctionSpace> ( */ public override val one: ListRationalFunction = ListRationalFunction(polynomialOne, polynomialOne) - // TODO: Разобрать + // 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. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun ListPolynomial.substitute(argument: C): C = this.substitute(ring, argument) + /** + * Substitutes provided polynomial [argument] into [this] polynomial. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun ListPolynomial.substitute(argument: ListPolynomial): ListPolynomial = this.substitute(ring, argument) + /** + * Substitutes provided rational function [argument] into [this] polynomial. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun ListPolynomial.substitute(argument: ListRationalFunction): ListRationalFunction = this.substitute(ring, argument) + /** + * Substitutes provided polynomial [argument] into [this] rational function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun ListRationalFunction.substitute(argument: ListPolynomial): ListRationalFunction = this.substitute(ring, argument) + /** + * Substitutes provided rational function [argument] into [this] rational function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun ListRationalFunction.substitute(argument: ListRationalFunction): ListRationalFunction = this.substitute(ring, argument) -// operator fun invoke(arg: UnivariatePolynomial): RationalFunction = -// RationalFunction( -// numerator(arg), -// denominator(arg) -// ) -// -// operator fun invoke(arg: RationalFunction): RationalFunction { -// val num = numerator invokeRFTakeNumerator arg -// val den = denominator invokeRFTakeNumerator arg -// val degreeDif = numeratorDegree - denominatorDegree -// return if (degreeDif > 0) -// RationalFunction( -// num, -// multiplyByPower(den, arg.denominator, degreeDif) -// ) -// else -// RationalFunction( -// multiplyByPower(num, arg.denominator, -degreeDif), -// den -// ) -// } -// -// override fun toString(): String = toString(UnivariatePolynomial.variableName) -// -// fun toString(withVariableName: String = UnivariatePolynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toString(withVariableName) -// else -> "${numerator.toStringWithBrackets(withVariableName)}/${denominator.toStringWithBrackets(withVariableName)}" -// } -// -// fun toStringWithBrackets(withVariableName: String = UnivariatePolynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toStringWithBrackets(withVariableName) -// else -> "(${numerator.toStringWithBrackets(withVariableName)}/${denominator.toStringWithBrackets(withVariableName)})" -// } -// -// fun toReversedString(withVariableName: String = UnivariatePolynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedString(withVariableName) -// else -> "${numerator.toReversedStringWithBrackets(withVariableName)}/${denominator.toReversedStringWithBrackets(withVariableName)}" -// } -// -// fun toReversedStringWithBrackets(withVariableName: String = UnivariatePolynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedStringWithBrackets(withVariableName) -// else -> "(${numerator.toReversedStringWithBrackets(withVariableName)}/${denominator.toReversedStringWithBrackets(withVariableName)})" -// } -// -// fun removeZeros() = -// RationalFunction( -// numerator.removeZeros(), -// denominator.removeZeros() -// ) + /** + * Represent [this] polynomial as a regular context-less function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun ListPolynomial.asFunction(): (C) -> C = { this.substitute(ring, it) } + /** + * Represent [this] polynomial as a regular context-less function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun ListPolynomial.asFunctionOfConstant(): (C) -> C = { this.substitute(ring, it) } + /** + * Represent [this] polynomial as a regular context-less function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun ListPolynomial.asFunctionOfPolynomial(): (ListPolynomial) -> ListPolynomial = { this.substitute(ring, it) } + /** + * Represent [this] polynomial as a regular context-less function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun ListPolynomial.asFunctionOfRationalFunction(): (ListRationalFunction) -> ListRationalFunction = { this.substitute(ring, it) } + /** + * Represent [this] rational function as a regular context-less function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun ListRationalFunction.asFunctionOfPolynomial(): (ListPolynomial) -> ListRationalFunction = { this.substitute(ring, it) } + /** + * Represent [this] rational function as a regular context-less function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun ListRationalFunction.asFunctionOfRationalFunction(): (ListRationalFunction) -> ListRationalFunction = { this.substitute(ring, it) } + + /** + * Evaluates value of [this] polynomial on provided argument. + */ + @Suppress("NOTHING_TO_INLINE") + public inline operator fun ListPolynomial.invoke(argument: C): C = this.substitute(ring, argument) + /** + * Evaluates value of [this] polynomial on provided argument. + */ + @Suppress("NOTHING_TO_INLINE") + public inline operator fun ListPolynomial.invoke(argument: ListPolynomial): ListPolynomial = this.substitute(ring, argument) + /** + * Evaluates value of [this] polynomial on provided argument. + */ + @Suppress("NOTHING_TO_INLINE") + public inline operator fun ListPolynomial.invoke(argument: ListRationalFunction): ListRationalFunction = this.substitute(ring, argument) + /** + * Evaluates value of [this] rational function on provided argument. + */ + @Suppress("NOTHING_TO_INLINE") + public inline operator fun ListRationalFunction.invoke(argument: ListPolynomial): ListRationalFunction = this.substitute(ring, argument) + /** + * Evaluates value of [this] rational function on provided argument. + */ + @Suppress("NOTHING_TO_INLINE") + public inline operator fun ListRationalFunction.invoke(argument: ListRationalFunction): ListRationalFunction = this.substitute(ring, argument) } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index f2eba10d5..12490d133 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -435,10 +435,12 @@ public interface MultivariatePolynomialSpace>: Polynomial /** * 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) /** diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index edc9dfa5c..4ce6c7c26 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -1060,12 +1060,12 @@ public abstract class PolynomialSpaceOfFractions< /** * Instance of zero rational function (zero of the rational functions ring). */ - public override val zero: R get() = constructRationalFunction(polynomialZero) + public override val zero: R by lazy { constructRationalFunction(polynomialZero) } /** * Instance of unit polynomial (unit of the rational functions ring). */ - public override val one: R get() = constructRationalFunction(polynomialOne) + public override val one: R by lazy { constructRationalFunction(polynomialOne) } } /** @@ -1177,19 +1177,23 @@ public interface MultivariateRationalFunctionalSpace< /** * 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") public fun number(variable: V): R = number(polynomialNumber(variable)) /** * Represents the variable as a rational function. */ + @JvmName("asRationalFunctionVariable") public fun V.asRationalFunction(): R = number(this) /** @@ -1403,10 +1407,12 @@ public interface MultivariateRationalFunctionalSpaceOverMultivariatePolynomialSp /** * 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() } /** diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt deleted file mode 100644 index 50313cab9..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.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.min -import kotlin.math.pow - - -/** - * Removes zeros on the end of the coefficient list of polynomial. - */ -//context(PolynomialSpace) -//fun > Polynomial.removeZeros() : Polynomial = -// if (degree > -1) Polynomial(coefficients.subList(0, degree + 1)) else zero - -/** - * Creates a [ListPolynomialSpace] over a received ring. - */ -public fun > A.listPolynomial(): ListPolynomialSpace = - ListPolynomialSpace(this) - -/** - * Creates a [ListPolynomialSpace]'s scope over a received ring. - */ -public inline fun , R> A.listPolynomial(block: ListPolynomialSpace.() -> R): R { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return ListPolynomialSpace(this).block() -} - -/** - * Creates a [ScalableListPolynomialSpace] over a received scalable ring. - */ -public fun A.scalableListPolynomial(): ScalableListPolynomialSpace where A : Ring, A : ScaleOperations = - ScalableListPolynomialSpace(this) - -/** - * Creates a [ScalableListPolynomialSpace]'s scope over a received scalable ring. - */ -public inline fun A.scalableListPolynomial(block: ScalableListPolynomialSpace.() -> R): R where A : Ring, A : ScaleOperations { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return ScalableListPolynomialSpace(this).block() -} - -@Suppress("NOTHING_TO_INLINE") -internal inline fun copyTo( - origin: List, - originDegree: Int, - target: MutableList, -) { - for (deg in 0 .. originDegree) target[deg] = origin[deg] -} - -@Suppress("NOTHING_TO_INLINE") -internal inline fun multiplyAddingToUpdater( - ring: Ring, - multiplicand: MutableList, - multiplicandDegree: Int, - multiplier: List, - multiplierDegree: Int, - updater: MutableList, - zero: C, -) { - multiplyAddingTo( - ring = ring, - multiplicand = multiplicand, - multiplicandDegree = multiplicandDegree, - multiplier = multiplier, - multiplierDegree = multiplierDegree, - target = updater - ) - for (updateDeg in 0 .. multiplicandDegree + multiplierDegree) { - multiplicand[updateDeg] = updater[updateDeg] - updater[updateDeg] = zero - } -} - -@Suppress("NOTHING_TO_INLINE") -internal inline fun multiplyAddingTo( - ring: Ring, - multiplicand: List, - multiplicandDegree: Int, - multiplier: List, - multiplierDegree: Int, - target: MutableList -) = ring { - for (d in 0 .. multiplicandDegree + multiplierDegree) - for (k in max(0, d - multiplierDegree)..min(multiplicandDegree, d)) - target[d] += multiplicand[k] * multiplier[d - k] -} - -/** - * Evaluates the value of the given double polynomial for given double argument. - */ -public fun ListPolynomial.substitute(arg: Double): Double = - coefficients.reduceIndexedOrNull { index, acc, c -> - acc + c * arg.pow(index) - } ?: .0 - -/** - * Evaluates the value of the given polynomial for given 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@ring zero - var result: C = coefficients.last() - for (j in coefficients.size - 2 downTo 0) { - result = (arg * result) + coefficients[j] - } - return result -} - -public fun ListPolynomial.substitute(ring: Ring, arg: ListPolynomial) : ListPolynomial = ring { - if (coefficients.isEmpty()) return ListPolynomial(emptyList()) - - val thisDegree = coefficients.lastIndex - if (thisDegree == -1) return ListPolynomial(emptyList()) - val argDegree = arg.coefficients.lastIndex - if (argDegree == -1) return coefficients[0].asListPolynomial() - val constantZero = zero - val resultCoefs: MutableList = MutableList(thisDegree * argDegree + 1) { constantZero } - resultCoefs[0] = coefficients[thisDegree] - val resultCoefsUpdate: MutableList = MutableList(thisDegree * argDegree + 1) { constantZero } - var resultDegree = 0 - for (deg in thisDegree - 1 downTo 0) { - resultCoefsUpdate[0] = coefficients[deg] - multiplyAddingToUpdater( - ring = ring, - multiplicand = resultCoefs, - multiplicandDegree = resultDegree, - multiplier = arg.coefficients, - multiplierDegree = argDegree, - updater = resultCoefsUpdate, - zero = constantZero - ) - resultDegree += argDegree - } - - return ListPolynomial(resultCoefs) -} - -/** - * Represent the polynomial as a regular context-less function. - */ -public fun > ListPolynomial.asFunction(ring: A): (C) -> C = { substitute(ring, it) } - -/** - * Represent the polynomial as a regular context-less function. - */ -public fun > ListPolynomial.asPolynomialFunctionOver(ring: A): (ListPolynomial) -> ListPolynomial = { substitute(ring, it) } - -/** - * Returns algebraic derivative of received polynomial. - */ -@UnstableKMathAPI -public fun ListPolynomial.derivative( - algebra: A, -): ListPolynomial where A : Ring, A : NumericAlgebra = algebra { - ListPolynomial( - buildList(max(0, coefficients.size - 1)) { - for (deg in 1 .. coefficients.lastIndex) add(number(deg) * coefficients[deg]) - } - ) -} - -/** - * Returns algebraic derivative of received polynomial. - */ -@UnstableKMathAPI -public fun ListPolynomial.nthDerivative( - algebra: A, - order: Int, -): ListPolynomial where A : Ring, A : NumericAlgebra = algebra { - 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( - algebra: A, -): ListPolynomial where A : Field, A : NumericAlgebra = algebra { - ListPolynomial( - buildList(coefficients.size + 1) { - add(zero) - coefficients.mapIndexedTo(this) { index, t -> t / number(index + 1) } - } - ) -} - -/** - * Returns algebraic antiderivative of received polynomial. - */ -@UnstableKMathAPI -public fun ListPolynomial.nthAntiderivative( - algebra: A, - order: Int, -): ListPolynomial where A : Field, A : NumericAlgebra = algebra { - 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) } } - } - ) -} - -/** - * Compute a definite integral of a given polynomial in a [range] - */ -@UnstableKMathAPI -public fun > ListPolynomial.integrate( - algebra: Field, - range: ClosedRange, -): C = algebra { - val integral = antiderivative(algebra) - integral.substitute(algebra, range.endInclusive) - integral.substitute(algebra, range.start) -} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt new file mode 100644 index 000000000..127dd8c7a --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt @@ -0,0 +1,268 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.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 fun > A.listPolynomialSpace(): ListPolynomialSpace = + 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 fun A.scalableListPolynomialSpace(): ScalableListPolynomialSpace where A : Ring, A : ScaleOperations = + 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 fun > A.listRationalFunctionSpace(): ListRationalFunctionSpace = + 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.asPolynomialFunctionOver(ring: A): (ListPolynomial) -> ListPolynomial = { substitute(ring, it) } + +/** + * Represent [this] polynomial as a regular context-less function. + */ +public fun > ListPolynomial.asFunctionOfRationalFunctionOver(ring: A): (ListPolynomial) -> ListPolynomial = { 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.asPolynomialFunctionOver(ring: A): (ListPolynomial) -> ListRationalFunction = { substitute(ring, it) } + +/** + * Represent [this] rational function as a regular context-less function. + */ +public fun > ListRationalFunction.asFunctionOfRationalFunctionOver(ring: A): (ListPolynomial) -> 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) +} + +/** + * Returns algebraic derivative of received rational function. + */ +@UnstableKMathAPI +public fun ListRationalFunction.derivative( + ring: A, +): ListRationalFunction where A : Ring, A : NumericAlgebra = ring.listRationalFunctionSpace { + ListRationalFunction( + numerator.derivative(ring) * denominator - numerator * denominator.derivative(ring), + denominator * denominator + ) +} + +/** + * Returns algebraic derivative of received rational function of specified [order]. The [order] should be non-negative integer. + */ +@UnstableKMathAPI +public tailrec fun ListRationalFunction.nthDerivative( + ring: A, + order: Int, +): ListRationalFunction where A : Ring, A : NumericAlgebra = + if (order == 0) this else derivative(ring).nthDerivative(ring, order - 1) \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listRationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtilOptimized.kt similarity index 72% rename from kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listRationalFunctionUtil.kt rename to kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtilOptimized.kt index 367212588..6eb3a1dc7 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listRationalFunctionUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtilOptimized.kt @@ -5,41 +5,91 @@ package space.kscience.kmath.functions -import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.invoke -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract import kotlin.math.max +import kotlin.math.min -/** - * Creates a [ListRationalFunctionSpace] over a received ring. - */ -public fun > A.listRationalFunction(): ListRationalFunctionSpace = - ListRationalFunctionSpace(this) - -/** - * Creates a [ListRationalFunctionSpace]'s scope over a received ring. - */ -public inline fun , R> A.listRationalFunction(block: ListRationalFunctionSpace.() -> R): R { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return ListRationalFunctionSpace(this).block() +// TODO: Optimized copies of substitution and invocation +@UnstablePolynomialBoxingOptimization +@Suppress("NOTHING_TO_INLINE") +internal inline fun copyTo( + origin: List, + originDegree: Int, + target: MutableList, +) { + for (deg in 0 .. originDegree) target[deg] = origin[deg] } -/** - * Evaluates the value of the given double polynomial for given double argument. - */ -public fun ListRationalFunction.substitute(arg: Double): Double = - numerator.substitute(arg) / denominator.substitute(arg) +@UnstablePolynomialBoxingOptimization +@Suppress("NOTHING_TO_INLINE") +internal inline fun multiplyAddingToUpdater( + ring: Ring, + multiplicand: MutableList, + multiplicandDegree: Int, + multiplier: List, + multiplierDegree: Int, + updater: MutableList, + zero: C, +) { + multiplyAddingTo( + ring = ring, + multiplicand = multiplicand, + multiplicandDegree = multiplicandDegree, + multiplier = multiplier, + multiplierDegree = multiplierDegree, + target = updater + ) + for (updateDeg in 0 .. multiplicandDegree + multiplierDegree) { + multiplicand[updateDeg] = updater[updateDeg] + updater[updateDeg] = zero + } +} -/** - * Evaluates the value of the given polynomial for given 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) +@UnstablePolynomialBoxingOptimization +@Suppress("NOTHING_TO_INLINE") +internal inline fun multiplyAddingTo( + ring: Ring, + multiplicand: List, + multiplicandDegree: Int, + multiplier: List, + multiplierDegree: Int, + target: MutableList +) = ring { + for (d in 0 .. multiplicandDegree + multiplierDegree) + for (k in max(0, d - multiplierDegree)..min(multiplicandDegree, d)) + target[d] += multiplicand[k] * multiplier[d - k] +} + +@UnstablePolynomialBoxingOptimization +public fun ListPolynomial.substitute2(ring: Ring, arg: ListPolynomial) : ListPolynomial = ring { + if (coefficients.isEmpty()) return ListPolynomial(emptyList()) + + val thisDegree = coefficients.lastIndex + if (thisDegree == -1) return ListPolynomial(emptyList()) + val argDegree = arg.coefficients.lastIndex + if (argDegree == -1) return coefficients[0].asListPolynomial() + val constantZero = zero + val resultCoefs: MutableList = MutableList(thisDegree * argDegree + 1) { constantZero } + resultCoefs[0] = coefficients[thisDegree] + val resultCoefsUpdate: MutableList = MutableList(thisDegree * argDegree + 1) { constantZero } + var resultDegree = 0 + for (deg in thisDegree - 1 downTo 0) { + resultCoefsUpdate[0] = coefficients[deg] + multiplyAddingToUpdater( + ring = ring, + multiplicand = resultCoefs, + multiplicandDegree = resultDegree, + multiplier = arg.coefficients, + multiplierDegree = argDegree, + updater = resultCoefsUpdate, + zero = constantZero + ) + resultDegree += argDegree + } + + return ListPolynomial(resultCoefs) } /** @@ -52,6 +102,7 @@ public fun ListRationalFunction.substitute(ring: Field, arg: C): C = r * * Used in [ListPolynomial.substitute] and [ListRationalFunction.substitute] for performance optimisation. */ // TODO: Дописать +@UnstablePolynomialBoxingOptimization internal fun ListPolynomial.substituteRationalFunctionTakeNumerator(ring: Ring, arg: ListRationalFunction): ListPolynomial = ring { if (coefficients.isEmpty()) return ListPolynomial(emptyList()) @@ -196,26 +247,4 @@ internal fun ListPolynomial.substituteRationalFunctionTakeNumerator(ring: end = thisDegree + 1 ) ) -} - -//operator fun > RationalFunction.invoke(arg: T): T = numerator(arg) / denominator(arg) -// -//fun > RationalFunction.reduced(): RationalFunction = -// polynomialGCD(numerator, denominator).let { -// RationalFunction( -// numerator / it, -// denominator / it -// ) -// } - -///** -// * Returns result of applying formal derivative to the polynomial. -// * -// * @param T Field where we are working now. -// * @return Result of the operator. -// */ -//fun > RationalFunction.derivative() = -// RationalFunction( -// numerator.derivative() * denominator - denominator.derivative() * numerator, -// denominator * denominator -// ) \ No newline at end of file +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt new file mode 100644 index 000000000..8b6fac39e --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + + +@RequiresOptIn( + message = "It's copy of operation with optimized boxing. It's currently unstable.", + level = RequiresOptIn.Level.ERROR +) +internal annotation class UnstablePolynomialBoxingOptimization \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt index c5eb8fb81..69c1611f3 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.functions +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.test.misc.Rational import space.kscience.kmath.test.misc.RationalField import kotlin.test.Test @@ -12,6 +13,7 @@ import kotlin.test.assertEquals import kotlin.test.assertFailsWith +@OptIn(UnstableKMathAPI::class) class ListPolynomialUtilTest { @Test fun test_substitute_Double() { diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt new file mode 100644 index 000000000..72bb5942c --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt @@ -0,0 +1,135 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.test.misc + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.Field +import space.kscience.kmath.operations.NumbersAddOps + +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 = + Rational( + numerator * other.denominator + denominator * other.numerator, + denominator * other.denominator + ) + operator fun plus(other: Int): Rational = + Rational( + numerator + denominator * other.toLong(), + denominator + ) + operator fun plus(other: Long): Rational = + Rational( + numerator + denominator * other, + denominator + ) + operator fun minus(other: Rational): Rational = + Rational( + numerator * other.denominator - denominator * other.numerator, + denominator * other.denominator + ) + operator fun minus(other: Int): Rational = + Rational( + numerator - denominator * other.toLong(), + denominator + ) + operator fun minus(other: Long): Rational = + Rational( + numerator - denominator * other, + denominator + ) + operator fun times(other: Rational): Rational = + Rational( + numerator * other.numerator, + denominator * other.denominator + ) + operator fun times(other: Int): Rational = + Rational( + numerator * other.toLong(), + denominator + ) + operator fun times(other: Long): Rational = + Rational( + numerator * other, + denominator + ) + operator fun div(other: Rational): Rational = + Rational( + numerator * other.denominator, + denominator * other.numerator + ) + operator fun div(other: Int): Rational = + Rational( + numerator, + denominator * other.toLong() + ) + operator fun div(other: Long): Rational = + Rational( + numerator, + denominator * other + ) + 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", "NOTHING_TO_INLINE") +@OptIn(UnstableKMathAPI::class) +object RationalField : Field, NumbersAddOps { + override inline val zero: Rational get() = Rational.ZERO + override inline val one: Rational get() = Rational.ONE + + override inline fun number(value: Number): Rational = Rational(value.toLong()) + + override inline fun add(left: Rational, right: Rational): Rational = left + right + override inline fun multiply(left: Rational, right: Rational): Rational = left * right + override inline fun divide(left: Rational, right: Rational): Rational = left / right + override inline fun scale(a: Rational, value: Double): Rational = a * number(value) + + override inline fun Rational.unaryMinus(): Rational = -this + override inline fun Rational.plus(arg: Rational): Rational = this + arg + override inline fun Rational.minus(arg: Rational): Rational = this - arg + override inline fun Rational.times(arg: Rational): Rational = this * arg + override inline fun Rational.div(arg: Rational): Rational = this / arg +} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt new file mode 100644 index 000000000..873162a1b --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt @@ -0,0 +1,11 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.test.misc + +import kotlin.math.abs + + +tailrec fun gcd(a: Long, b: Long): Long = if (a == 0L) abs(b) else gcd(b % a, a) \ No newline at end of file -- 2.34.1 From e7100138006c0b7f91ee40135a40498b09ddeebe Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sun, 12 Jun 2022 23:02:26 +0300 Subject: [PATCH 084/275] Fixed tests. --- .../kmath/functions/ListPolynomialTest.kt | 32 ++-- .../kscience/kmath/test/misc/IntModulo.kt | 140 ++++++++++++++++++ .../space/kscience/kmath/test/misc/misc.kt | 20 ++- 3 files changed, 175 insertions(+), 17 deletions(-) create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt index 5401be707..c9950fac5 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt @@ -12,7 +12,7 @@ import kotlin.test.* class ListPolynomialTest { @Test fun test_Polynomial_Int_plus() { - RationalField.listPolynomial { + RationalField.listPolynomialSpace { assertEquals( ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)), ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + -3, @@ -52,7 +52,7 @@ class ListPolynomialTest { } @Test fun test_Polynomial_Int_minus() { - RationalField.listPolynomial { + RationalField.listPolynomialSpace { assertEquals( ListPolynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - -3, @@ -92,7 +92,7 @@ class ListPolynomialTest { } @Test fun test_Polynomial_Int_times() { - IntModuloRing(35).listPolynomial { + IntModuloRing(35).listPolynomialSpace { assertEquals( ListPolynomial(34, 2, 1, 20, 2), ListPolynomial(22, 26, 13, 15, 26) * 27, @@ -107,7 +107,7 @@ class ListPolynomialTest { } @Test fun test_Int_Polynomial_plus() { - RationalField.listPolynomial { + RationalField.listPolynomialSpace { assertEquals( ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)), -3 + ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)), @@ -147,7 +147,7 @@ class ListPolynomialTest { } @Test fun test_Int_Polynomial_minus() { - RationalField.listPolynomial { + RationalField.listPolynomialSpace { assertEquals( ListPolynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), 3 - ListPolynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7)), @@ -187,7 +187,7 @@ class ListPolynomialTest { } @Test fun test_Int_Polynomial_times() { - IntModuloRing(35).listPolynomial { + IntModuloRing(35).listPolynomialSpace { assertEquals( ListPolynomial(34, 2, 1, 20, 2), 27 * ListPolynomial(22, 26, 13, 15, 26), @@ -202,7 +202,7 @@ class ListPolynomialTest { } @Test fun test_Polynomial_Constant_plus() { - RationalField.listPolynomial { + 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), @@ -242,7 +242,7 @@ class ListPolynomialTest { } @Test fun test_Polynomial_Constant_minus() { - RationalField.listPolynomial { + 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), @@ -282,7 +282,7 @@ class ListPolynomialTest { } @Test fun test_Polynomial_Constant_times() { - IntModuloRing(35).listPolynomial { + IntModuloRing(35).listPolynomialSpace { assertEquals( ListPolynomial(34, 2, 1, 20, 2), ListPolynomial(22, 26, 13, 15, 26) * 27.asConstant(), @@ -297,7 +297,7 @@ class ListPolynomialTest { } @Test fun test_Constant_Polynomial_plus() { - RationalField.listPolynomial { + 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)), @@ -337,7 +337,7 @@ class ListPolynomialTest { } @Test fun test_Constant_Polynomial_minus() { - RationalField.listPolynomial { + 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)), @@ -377,7 +377,7 @@ class ListPolynomialTest { } @Test fun test_Constant_Polynomial_times() { - IntModuloRing(35).listPolynomial { + IntModuloRing(35).listPolynomialSpace { assertEquals( ListPolynomial(34, 2, 1, 20, 2), 27 * ListPolynomial(22, 26, 13, 15, 26), @@ -392,7 +392,7 @@ class ListPolynomialTest { } @Test fun test_Polynomial_unaryMinus() { - RationalField.listPolynomial { + RationalField.listPolynomialSpace { assertEquals( ListPolynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7)), -ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)), @@ -407,7 +407,7 @@ class ListPolynomialTest { } @Test fun test_Polynomial_Polynomial_plus() { - RationalField.listPolynomial { + 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)), @@ -440,7 +440,7 @@ class ListPolynomialTest { } @Test fun test_Polynomial_Polynomial_minus() { - RationalField.listPolynomial { + 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)), @@ -473,7 +473,7 @@ class ListPolynomialTest { } @Test fun test_Polynomial_Polynomial_times() { - IntModuloRing(35).listPolynomial { + IntModuloRing(35).listPolynomialSpace { // (1 + x + x^2) * (1 - x + x^2) ?= 1 + x^2 + x^4 assertEquals( ListPolynomial(1, 0, 1, 0, 1), diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt new file mode 100644 index 000000000..36a0d8be5 --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt @@ -0,0 +1,140 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.test.misc + +import space.kscience.kmath.functions.ListPolynomial +import space.kscience.kmath.functions.ListPolynomialSpace +import space.kscience.kmath.misc.UnstableKMathAPI +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(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", "NOTHING_TO_INLINE") +@OptIn(UnstableKMathAPI::class) +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(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 +} + +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) }) \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt index 873162a1b..ed41b9245 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt @@ -8,4 +8,22 @@ package space.kscience.kmath.test.misc import kotlin.math.abs -tailrec fun gcd(a: Long, b: Long): Long = if (a == 0L) abs(b) else gcd(b % a, a) \ No newline at end of file +data class BezoutIdentityWithGCD(val first: T, val second: T, val gcd: T) + +tailrec fun gcd(a: Long, b: Long): Long = if (a == 0L) abs(b) else gcd(b % a, a) + +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 -- 2.34.1 From 94fd24d8524140c945412b980df8e5252a10e811 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sun, 12 Jun 2022 23:49:44 +0300 Subject: [PATCH 085/275] Fixed some tests and docstrings. Removed `zero` and `one` overridings because overrided fields are already lazily initialized. --- .../kmath/functions/ListRationalFunction.kt | 9 ----- .../kmath/functions/RationalFunction.kt | 34 +++++++++++++++---- .../kscience/kmath/test/misc/IntModulo.kt | 2 -- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt index 45ea99fb0..f3e352bcd 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt @@ -50,15 +50,6 @@ public class ListRationalFunctionSpace> ( override fun constructRationalFunction(numerator: ListPolynomial, denominator: ListPolynomial): ListRationalFunction = ListRationalFunction(numerator, denominator) - /** - * Instance of zero rational function (zero of the rational functions ring). - */ - public override val zero: ListRationalFunction = ListRationalFunction(polynomialZero, polynomialOne) - /** - * Instance of unit polynomial (unit of the rational functions ring). - */ - public override val one: ListRationalFunction = ListRationalFunction(polynomialOne, polynomialOne) - // TODO: When context receivers will be ready move all of this substitutions and invocations to utilities with // [ListPolynomialSpace] as a context receiver /** diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index 4ce6c7c26..01911f980 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -834,7 +834,12 @@ public abstract class PolynomialSpaceOfFractions< 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, @@ -871,7 +876,12 @@ public abstract class PolynomialSpaceOfFractions< 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, @@ -912,7 +922,9 @@ public abstract class PolynomialSpaceOfFractions< this * other.numerator, other.denominator ) - + /** + * Returns quotient of the constant represented as a polynomial and the rational function. + */ public override operator fun C.div(other: R): R = constructRationalFunction( this * other.denominator, @@ -943,7 +955,9 @@ public abstract class PolynomialSpaceOfFractions< numerator * other, denominator ) - + /** + * Returns quotient of the rational function and the constant represented as a rational function. + */ public override operator fun R.div(other: C): R = constructRationalFunction( numerator, @@ -979,7 +993,9 @@ public abstract class PolynomialSpaceOfFractions< this * other.numerator, other.denominator ) - + /** + * Returns quotient of the polynomial represented as a polynomial and the rational function. + */ public override operator fun P.div(other: R): R = constructRationalFunction( this * other.denominator, @@ -1010,7 +1026,9 @@ public abstract class PolynomialSpaceOfFractions< numerator * other, denominator ) - + /** + * Returns quotient of the rational function and the polynomial represented as a rational function. + */ public override operator fun R.div(other: P): R = constructRationalFunction( numerator, @@ -1050,7 +1068,9 @@ public abstract class PolynomialSpaceOfFractions< 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, diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt index 36a0d8be5..89764db46 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt @@ -7,7 +7,6 @@ package space.kscience.kmath.test.misc import space.kscience.kmath.functions.ListPolynomial import space.kscience.kmath.functions.ListPolynomialSpace -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Ring @@ -109,7 +108,6 @@ class IntModulo { } @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") -@OptIn(UnstableKMathAPI::class) class IntModuloRing : Ring { val modulus: Int -- 2.34.1 From ab9bba22022187b0437e9fc085b16cd8cbf232fe Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Mon, 13 Jun 2022 00:16:22 +0300 Subject: [PATCH 086/275] Put suddenly disappeared files back. --- .../kmath/functions/listConstructors.kt | 65 +++++++++ .../kscience/kmath/test/misc/Rational.kt | 135 ++++++++++++++++++ 2 files changed, 200 insertions(+) create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt new file mode 100644 index 000000000..fc55ba310 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt @@ -0,0 +1,65 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.Ring + + +/** + * Returns a [ListPolynomial] instance with given [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 }) + +/** + * Returns a [ListPolynomial] instance with given [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() }) + +public fun C.asListPolynomial() : ListPolynomial = ListPolynomial(listOf(this)) + + +// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available + +@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 } ) + ) +@Suppress("FunctionName") +public fun > ListRationalFunctionSpace.ListRationalFunction(numerator: ListPolynomial): ListRationalFunction = + ListRationalFunction(numerator, polynomialOne) +@Suppress("FunctionName") +public fun > A.ListRationalFunction(numerator: ListPolynomial): ListRationalFunction = + ListRationalFunction(numerator, ListPolynomial(listOf(one))) +@Suppress("FunctionName") +public fun > ListRationalFunctionSpace.ListRationalFunction(numeratorCoefficients: List, reverse: Boolean = false): ListRationalFunction = + ListRationalFunction( + ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), + polynomialOne + ) +@Suppress("FunctionName") +public fun > A.ListRationalFunction(numeratorCoefficients: List, reverse: Boolean = false): ListRationalFunction = + ListRationalFunction( + ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), + ListPolynomial(listOf(one)) + ) + +//context(A) +//public fun > C.asListRationalFunction() : ListRationalFunction = ListRationalFunction(asListPolynomial()) +//context(ListRationalFunctionSpace) +//public fun > C.asListRationalFunction() : ListRationalFunction = ListRationalFunction(asListPolynomial()) \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt new file mode 100644 index 000000000..72bb5942c --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt @@ -0,0 +1,135 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.test.misc + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.Field +import space.kscience.kmath.operations.NumbersAddOps + +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 = + Rational( + numerator * other.denominator + denominator * other.numerator, + denominator * other.denominator + ) + operator fun plus(other: Int): Rational = + Rational( + numerator + denominator * other.toLong(), + denominator + ) + operator fun plus(other: Long): Rational = + Rational( + numerator + denominator * other, + denominator + ) + operator fun minus(other: Rational): Rational = + Rational( + numerator * other.denominator - denominator * other.numerator, + denominator * other.denominator + ) + operator fun minus(other: Int): Rational = + Rational( + numerator - denominator * other.toLong(), + denominator + ) + operator fun minus(other: Long): Rational = + Rational( + numerator - denominator * other, + denominator + ) + operator fun times(other: Rational): Rational = + Rational( + numerator * other.numerator, + denominator * other.denominator + ) + operator fun times(other: Int): Rational = + Rational( + numerator * other.toLong(), + denominator + ) + operator fun times(other: Long): Rational = + Rational( + numerator * other, + denominator + ) + operator fun div(other: Rational): Rational = + Rational( + numerator * other.denominator, + denominator * other.numerator + ) + operator fun div(other: Int): Rational = + Rational( + numerator, + denominator * other.toLong() + ) + operator fun div(other: Long): Rational = + Rational( + numerator, + denominator * other + ) + 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", "NOTHING_TO_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 -- 2.34.1 From dbb48a2a9f3ecabc0eb0aeb7e7c72d589aba0c4f Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Mon, 13 Jun 2022 01:41:04 +0300 Subject: [PATCH 087/275] Added docstrings to ListPolynomial and ListRationalFunction fabric functions. --- .../kmath/functions/listConstructors.kt | 56 +++++++++++++++---- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt index fc55ba310..35c736914 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt @@ -14,52 +14,84 @@ import space.kscience.kmath.operations.Ring /** - * Returns a [ListPolynomial] instance with given [coefficients]. The collection of coefficients will be reversed if - * [reverse] parameter is true. + * 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 }) /** - * Returns a [ListPolynomial] instance with given [coefficients]. The collection of coefficients will be reversed if - * [reverse] parameter is true. + * 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 } ) ) -@Suppress("FunctionName") -public fun > ListRationalFunctionSpace.ListRationalFunction(numerator: ListPolynomial): ListRationalFunction = - ListRationalFunction(numerator, polynomialOne) +/** + * 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(numeratorCoefficients: List, reverse: Boolean = false): ListRationalFunction = - ListRationalFunction( - ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), - polynomialOne - ) +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 -- 2.34.1 From 37ad48e820cde271ba93d1249b84b0abfd033f21 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Mon, 13 Jun 2022 02:06:15 +0300 Subject: [PATCH 088/275] Sift # 3. Filtered last sift and usages of [ListPolynomial]s. --- .../kmath/functions/LabeledPolynomial.kt | 539 ------------------ .../functions/LabeledRationalFunction.kt | 139 ----- .../kmath/functions/ListPolynomial.kt | 80 ++- .../kmath/functions/ListRationalFunction.kt | 158 +++-- .../kmath/functions/NumberedPolynomial.kt | 389 ------------- .../functions/NumberedRationalFunction.kt | 188 ------ .../kscience/kmath/functions/Polynomial.kt | 152 ++++- .../kmath/functions/RationalFunction.kt | 511 ++++++++++++----- .../kmath/functions/labeledConstructors.kt | 203 ------- .../kmath/functions/labeledPolynomialUtil.kt | 495 ---------------- .../functions/labeledRationalFunctionUtil.kt | 33 -- .../kmath/functions/listConstructors.kt | 61 +- .../kmath/functions/listPolynomialUtil.kt | 233 -------- .../kscience/kmath/functions/listUtil.kt | 268 +++++++++ ...alFunctionUtil.kt => listUtilOptimized.kt} | 129 +++-- .../space/kscience/kmath/functions/misc.kt | 13 + .../kmath/functions/numberedConstructors.kt | 195 ------- .../kmath/functions/numberedPolynomialUtil.kt | 528 ----------------- .../functions/numberedRationalFunctionUtil.kt | 33 -- .../kmath/functions/ListPolynomialTest.kt | 32 +- .../kmath/functions/ListPolynomialUtilTest.kt | 2 + .../kscience/kmath/test/misc/IntModulo.kt | 138 +++++ .../kscience/kmath/test/misc/Rational.kt | 135 +++++ .../space/kscience/kmath/test/misc/misc.kt | 29 + 24 files changed, 1378 insertions(+), 3305 deletions(-) delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt rename kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/{listRationalFunctionUtil.kt => listUtilOptimized.kt} (72%) create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt deleted file mode 100644 index b904f7331..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ /dev/null @@ -1,539 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.ScaleOperations -import kotlin.math.max - - -/** - * Represents multivariate polynomials with labeled variables. - * - * @param C Ring in which the polynomial is considered. - */ -public data class LabeledPolynomial -internal constructor( - /** - * Map that collects coefficients of the polynomial. Every non-zero monomial - * `a x_1^{d_1} ... x_n^{d_n}` is represented as pair "key-value" in the map, where value is coefficients `a` and - * key is map that associates variables in the monomial with multiplicity of them occurring in the monomial. - * For example polynomial - * ``` - * 5 a^2 c^3 - 6 b + 0 b c - * ``` - * has coefficients represented as - * ``` - * mapOf( - * mapOf( - * a to 2, - * c to 3 - * ) to 5, - * mapOf( - * b to 1 - * ) to (-6) - * ) - * ``` - * where `a`, `b` and `c` are corresponding [Symbol] objects. - */ - public val coefficients: Map, C> -) : Polynomial { - override fun toString(): String = "LabeledPolynomial$coefficients" -} - -/** - * Space of polynomials. - * - * @param C the type of operated polynomials. - * @param A the intersection of [Ring] of [C] and [ScaleOperations] of [C]. - * @param ring the [A] instance. - */ -public class LabeledPolynomialSpace>( - public override val ring: A, -) : MultivariatePolynomialSpace>, PolynomialSpaceOverRing, A> { - public override operator fun Symbol.plus(other: Int): LabeledPolynomial = - if (other == 0) LabeledPolynomial(mapOf( - mapOf(this@plus to 1U) to constantOne, - )) - else LabeledPolynomial(mapOf( - mapOf(this@plus to 1U) to constantOne, - emptyMap() to constantOne * other, - )) - public override operator fun Symbol.minus(other: Int): LabeledPolynomial = - if (other == 0) LabeledPolynomial(mapOf( - mapOf(this@minus to 1U) to -constantOne, - )) - else LabeledPolynomial(mapOf( - mapOf(this@minus to 1U) to -constantOne, - emptyMap() to constantOne * other, - )) - public override operator fun Symbol.times(other: Int): LabeledPolynomial = - if (other == 0) zero - else LabeledPolynomial(mapOf( - mapOf(this to 1U) to constantOne * other, - )) - - public override operator fun Int.plus(other: Symbol): LabeledPolynomial = - if (this == 0) LabeledPolynomial(mapOf( - mapOf(other to 1U) to constantOne, - )) - else LabeledPolynomial(mapOf( - mapOf(other to 1U) to constantOne, - emptyMap() to constantOne * this@plus, - )) - public override operator fun Int.minus(other: Symbol): LabeledPolynomial = - if (this == 0) LabeledPolynomial(mapOf( - mapOf(other to 1U) to -constantOne, - )) - else LabeledPolynomial(mapOf( - mapOf(other to 1U) to -constantOne, - emptyMap() to constantOne * this@minus, - )) - public override operator fun Int.times(other: Symbol): LabeledPolynomial = - if (this == 0) zero - else LabeledPolynomial(mapOf( - mapOf(other to 1U) to constantOne * this@times, - )) - - /** - * Returns sum of the polynomial and the integer represented as polynomial. - * - * The operation is equivalent to adding [other] copies of unit polynomial to [this]. - */ - public override operator fun LabeledPolynomial.plus(other: Int): LabeledPolynomial = - if (other == 0) this - else with(coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to other.asConstant())) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = emptyMap() - - this[degs] = getOrElse(degs) { constantZero } + other - } - ) - } - /** - * Returns difference between the polynomial and the integer represented as polynomial. - * - * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. - */ - public override operator fun LabeledPolynomial.minus(other: Int): LabeledPolynomial = - if (other == 0) this - else with(coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to (-other).asConstant())) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = emptyMap() - - this[degs] = getOrElse(degs) { constantZero } - other - } - ) - } - /** - * Returns product of the polynomial and the integer represented as polynomial. - * - * The operation is equivalent to sum of [other] copies of [this]. - */ - public override operator fun LabeledPolynomial.times(other: Int): LabeledPolynomial = - if (other == 0) zero - else LabeledPolynomial( - coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this[degs]!! * other - } - ) - - /** - * Returns sum of the integer represented as 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 = - if (this == 0) other - else with(other.coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@plus.asConstant())) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = emptyMap() - - this[degs] = this@plus + getOrElse(degs) { constantZero } - } - ) - } - /** - * Returns difference between the integer represented as 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 = - if (this == 0) other - else with(other.coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@minus.asConstant())) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = emptyMap() - - this[degs] = this@minus - getOrElse(degs) { constantZero } - } - ) - } - /** - * Returns product of the integer represented as polynomial and the polynomial. - * - * The operation is equivalent to sum of [this] copies of [other]. - */ - public override operator fun Int.times(other: LabeledPolynomial): LabeledPolynomial = - if (this == 0) zero - else LabeledPolynomial( - other.coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this@times * this[degs]!! - } - ) - - /** - * Converts the integer [value] to polynomial. - */ - public override fun number(value: Int): LabeledPolynomial = number(constantNumber(value)) - - public override operator fun C.plus(other: Symbol): LabeledPolynomial = - LabeledPolynomial(mapOf( - mapOf(other to 1U) to constantOne, - emptyMap() to this@plus, - )) - public override operator fun C.minus(other: Symbol): LabeledPolynomial = - LabeledPolynomial(mapOf( - mapOf(other to 1U) to -constantOne, - emptyMap() to this@minus, - )) - public override operator fun C.times(other: Symbol): LabeledPolynomial = - LabeledPolynomial(mapOf( - mapOf(other to 1U) to this@times, - )) - - public override operator fun Symbol.plus(other: C): LabeledPolynomial = - LabeledPolynomial(mapOf( - mapOf(this@plus to 1U) to constantOne, - emptyMap() to other, - )) - public override operator fun Symbol.minus(other: C): LabeledPolynomial = - LabeledPolynomial(mapOf( - mapOf(this@minus to 1U) to -constantOne, - emptyMap() to other, - )) - public override operator fun Symbol.times(other: C): LabeledPolynomial = - LabeledPolynomial(mapOf( - mapOf(this@times to 1U) to other, - )) - - /** - * Returns sum of the constant represented as polynomial and the polynomial. - */ - override operator fun C.plus(other: LabeledPolynomial): LabeledPolynomial = - with(other.coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@plus)) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = emptyMap() - - this[degs] = this@plus + getOrElse(degs) { constantZero } - } - ) - } - /** - * Returns difference between the constant represented as polynomial and the polynomial. - */ - override operator fun C.minus(other: LabeledPolynomial): LabeledPolynomial = - with(other.coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@minus)) - else LabeledPolynomial( - toMutableMap() - .apply { - forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } - - val degs = emptyMap() - - this[degs] = this@minus - getOrElse(degs) { constantZero } - } - ) - } - /** - * Returns product of the constant represented as polynomial and the polynomial. - */ - override operator fun C.times(other: LabeledPolynomial): LabeledPolynomial = - LabeledPolynomial( - other.coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this@times * this[degs]!! - } - ) - - /** - * Returns sum of the constant represented as polynomial and the polynomial. - */ - override operator fun LabeledPolynomial.plus(other: C): LabeledPolynomial = - with(coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to other)) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = emptyMap() - - this[degs] = getOrElse(degs) { constantZero } + other - } - ) - } - /** - * Returns difference between the constant represented as polynomial and the polynomial. - */ - override operator fun LabeledPolynomial.minus(other: C): LabeledPolynomial = - with(coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to other)) - else LabeledPolynomial( - toMutableMap() - .apply { - forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } - - val degs = emptyMap() - - this[degs] = getOrElse(degs) { constantZero } - other - } - ) - } - /** - * Returns product of the constant represented as polynomial and the polynomial. - */ - override operator fun LabeledPolynomial.times(other: C): LabeledPolynomial = - LabeledPolynomial( - coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this[degs]!! * other - } - ) - - /** - * Converts the constant [value] to polynomial. - */ - public override fun number(value: C): LabeledPolynomial = - LabeledPolynomial(mapOf(emptyMap() to value)) - - public override operator fun Symbol.unaryPlus(): LabeledPolynomial = - LabeledPolynomial(mapOf( - mapOf(this to 1U) to constantOne, - )) - public override operator fun Symbol.unaryMinus(): LabeledPolynomial = - LabeledPolynomial(mapOf( - mapOf(this to 1U) to -constantOne, - )) - public override operator fun Symbol.plus(other: Symbol): LabeledPolynomial = - if (this == other) LabeledPolynomial(mapOf( - mapOf(this to 1U) to constantOne * 2 - )) - else LabeledPolynomial(mapOf( - mapOf(this to 1U) to constantOne, - mapOf(other to 1U) to constantOne, - )) - public override operator fun Symbol.minus(other: Symbol): LabeledPolynomial = - if (this == other) zero - else LabeledPolynomial(mapOf( - mapOf(this to 1U) to constantOne, - mapOf(other to 1U) to -constantOne, - )) - public override operator fun Symbol.times(other: Symbol): LabeledPolynomial = - if (this == other) LabeledPolynomial(mapOf( - mapOf(this to 2U) to constantOne - )) - else LabeledPolynomial(mapOf( - mapOf(this to 1U, other to 1U) to constantOne, - )) - - public override operator fun Symbol.plus(other: LabeledPolynomial): LabeledPolynomial = - with(other.coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(mapOf(this@plus to 1u) to constantOne)) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = mapOf(this@plus to 1U) - - this[degs] = constantOne + getOrElse(degs) { constantZero } - } - ) - } - public override operator fun Symbol.minus(other: LabeledPolynomial): LabeledPolynomial = - with(other.coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(mapOf(this@minus to 1u) to constantOne)) - else LabeledPolynomial( - toMutableMap() - .apply { - forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } - - val degs = mapOf(this@minus to 1U) - - this[degs] = constantOne - getOrElse(degs) { constantZero } - } - ) - } - public override operator fun Symbol.times(other: LabeledPolynomial): LabeledPolynomial = - LabeledPolynomial( - other.coefficients - .mapKeys { (degs, _) -> degs.toMutableMap().also{ it[this] = if (this in it) it[this]!! + 1U else 1U } } - ) - - public override operator fun LabeledPolynomial.plus(other: Symbol): LabeledPolynomial = - with(coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(mapOf(other to 1u) to constantOne)) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = mapOf(other to 1U) - - this[degs] = constantOne + getOrElse(degs) { constantZero } - } - ) - } - public override operator fun LabeledPolynomial.minus(other: Symbol): LabeledPolynomial = - with(coefficients) { - if (isEmpty()) LabeledPolynomial(mapOf(mapOf(other to 1u) to constantOne)) - else LabeledPolynomial( - toMutableMap() - .apply { - val degs = mapOf(other to 1U) - - this[degs] = constantOne - getOrElse(degs) { constantZero } - } - ) - } - public override operator fun LabeledPolynomial.times(other: Symbol): LabeledPolynomial = - LabeledPolynomial( - coefficients - .mapKeys { (degs, _) -> degs.toMutableMap().also{ it[other] = if (other in it) it[other]!! + 1U else 1U } } - ) - - /** - * Returns negation of the polynomial. - */ - override fun LabeledPolynomial.unaryMinus(): LabeledPolynomial = - LabeledPolynomial( - coefficients.mapValues { -it.value } - ) - /** - * Returns sum of the polynomials. - */ - override operator fun LabeledPolynomial.plus(other: LabeledPolynomial): LabeledPolynomial = - LabeledPolynomial( - buildMap(coefficients.size + other.coefficients.size) { - other.coefficients.mapValuesTo(this) { it.value } - other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value } - } - ) - /** - * Returns difference of the polynomials. - */ - override operator fun LabeledPolynomial.minus(other: LabeledPolynomial): LabeledPolynomial = - LabeledPolynomial( - buildMap(coefficients.size + other.coefficients.size) { - other.coefficients.mapValuesTo(this) { it.value } - other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value } - } - ) - /** - * Returns product of the polynomials. - */ - override operator fun LabeledPolynomial.times(other: LabeledPolynomial): LabeledPolynomial = - LabeledPolynomial( - buildMap(coefficients.size * other.coefficients.size) { - for ((degs1, c1) in coefficients) for ((degs2, c2) in other.coefficients) { - val degs = degs1.toMutableMap() - degs2.mapValuesTo(degs) { (variable, deg) -> degs.getOrElse(variable) { 0u } + deg } - val c = c1 * c2 - this[degs] = if (degs in this) this[degs]!! + c else c - } - } - ) - - /** - * Instance of zero polynomial (zero of the polynomial ring). - */ - override val zero: LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to constantZero)) - /** - * Instance of unit polynomial (unit of the polynomial ring). - */ - override val one: LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to constantOne)) - - /** - * 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, c) -> 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.entries.forEach { (degs, _) -> - degs.mapValuesTo(this) { (variable, deg) -> - max(getOrElse(variable) { 0u }, deg) - } - } - } - /** - * 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 - -// @Suppress("NOTHING_TO_INLINE") -// public inline fun LabeledPolynomial.substitute(argument: Map): LabeledPolynomial = this.substitute(ring, argument) -// @Suppress("NOTHING_TO_INLINE") -// @JvmName("substitutePolynomial") -// public inline fun LabeledPolynomial.substitute(argument: Map>): LabeledPolynomial = this.substitute(ring, argument) -// -// @Suppress("NOTHING_TO_INLINE") -// public inline fun LabeledPolynomial.asFunction(): (Map) -> LabeledPolynomial = { this.substitute(ring, it) } -// @Suppress("NOTHING_TO_INLINE") -// public inline fun LabeledPolynomial.asFunctionOnConstants(): (Map) -> LabeledPolynomial = { this.substitute(ring, it) } -// @Suppress("NOTHING_TO_INLINE") -// public inline fun LabeledPolynomial.asFunctionOnPolynomials(): (Map>) -> LabeledPolynomial = { this.substitute(ring, it) } -// -// @Suppress("NOTHING_TO_INLINE") -// public inline operator fun LabeledPolynomial.invoke(argument: Map): LabeledPolynomial = this.substitute(ring, argument) -// @Suppress("NOTHING_TO_INLINE") -// @JvmName("invokePolynomial") -// public inline operator fun LabeledPolynomial.invoke(argument: Map>): LabeledPolynomial = this.substitute(ring, argument) -} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt deleted file mode 100644 index 76c6874f5..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.invoke - - -public class LabeledRationalFunction( - public override val numerator: LabeledPolynomial, - public override val denominator: LabeledPolynomial -) : RationalFunction> { - override fun toString(): String = "LabeledRationalFunction${numerator.coefficients}/${denominator.coefficients}" -} - -public class LabeledRationalFunctionSpace>( - public val ring: A, -) : - MultivariateRationalFunctionalSpaceOverMultivariatePolynomialSpace< - C, - Symbol, - LabeledPolynomial, - LabeledRationalFunction, - LabeledPolynomialSpace, - >, - MultivariatePolynomialSpaceOfFractions< - C, - Symbol, - LabeledPolynomial, - LabeledRationalFunction, - >() { - - override val polynomialRing : LabeledPolynomialSpace = LabeledPolynomialSpace(ring) - override fun constructRationalFunction( - numerator: LabeledPolynomial, - denominator: LabeledPolynomial - ): LabeledRationalFunction = - LabeledRationalFunction(numerator, denominator) - - /** - * Instance of zero rational function (zero of the rational functions ring). - */ - public override val zero: LabeledRationalFunction = LabeledRationalFunction(polynomialZero, polynomialOne) - /** - * Instance of unit polynomial (unit of the rational functions ring). - */ - public override val one: LabeledRationalFunction = LabeledRationalFunction(polynomialOne, polynomialOne) - - // TODO: Разобрать - -// operator fun invoke(arg: Map): LabeledRationalFunction = -// LabeledRationalFunction( -// numerator(arg), -// denominator(arg) -// ) -// -// @JvmName("invokeLabeledPolynomial") -// operator fun invoke(arg: Map>): LabeledRationalFunction = -// LabeledRationalFunction( -// numerator(arg), -// denominator(arg) -// ) -// -// @JvmName("invokeLabeledRationalFunction") -// operator fun invoke(arg: Map>): LabeledRationalFunction { -// var num = numerator invokeRFTakeNumerator arg -// var den = denominator invokeRFTakeNumerator arg -// for (variable in variables) if (variable in arg) { -// val degreeDif = degrees[variable]!! -// if (degreeDif > 0) -// den = multiplyByPower(den, arg[variable]!!.denominator, degreeDif) -// else -// num = multiplyByPower(num, arg[variable]!!.denominator, -degreeDif) -// } -// return LabeledRationalFunction(num, den) -// } -// -// override fun toString(): String = toString(emptyMap()) -// -// fun toString(names: Map = emptyMap()): String = -// when (true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toString(names) -// else -> "${numerator.toStringWithBrackets(names)}/${denominator.toStringWithBrackets(names)}" -// } -// -// fun toString(namer: (Symbol) -> String): String = -// when (true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toString(namer) -// else -> "${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)}" -// } -// -// fun toStringWithBrackets(names: Map = emptyMap()): String = -// when (true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toStringWithBrackets(names) -// else -> "(${numerator.toStringWithBrackets(names)}/${denominator.toStringWithBrackets(names)})" -// } -// -// fun toStringWithBrackets(namer: (Symbol) -> String): String = -// when (true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toStringWithBrackets(namer) -// else -> "(${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)})" -// } -// -// fun toReversedString(names: Map = emptyMap()): String = -// when (true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedString(names) -// else -> "${numerator.toReversedStringWithBrackets(names)}/${denominator.toReversedStringWithBrackets(names)}" -// } -// -// fun toReversedString(namer: (Symbol) -> String): String = -// when (true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedString(namer) -// else -> "${numerator.toReversedStringWithBrackets(namer)}/${denominator.toReversedStringWithBrackets(namer)}" -// } -// -// fun toReversedStringWithBrackets(names: Map = emptyMap()): String = -// when (true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedStringWithBrackets(names) -// else -> "(${numerator.toReversedStringWithBrackets(names)}/${denominator.toReversedStringWithBrackets(names)})" -// } -// -// fun toReversedStringWithBrackets(namer: (Symbol) -> String): String = -// when (true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedStringWithBrackets(namer) -// else -> "(${numerator.toReversedStringWithBrackets(namer)}/${denominator.toReversedStringWithBrackets(namer)})" -// } -} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt index 585da95ea..fce179fc8 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt @@ -8,23 +8,19 @@ 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.contracts.InvocationKind -import kotlin.contracts.contract -import kotlin.experimental.ExperimentalTypeInference -import kotlin.jvm.JvmName import kotlin.math.max import kotlin.math.min /** - * Polynomial model without fixation on specific context they are applied to. + * Represents univariate polynomial that stores its coefficients in a [List]. * * @param coefficients constant is the leftmost coefficient. */ public data class ListPolynomial( /** - * List that collects coefficients of the polynomial. Every monomial `a x^d` is represented as a coefficients - * `a` placed into the list with index `d`. For example coefficients of polynomial `5 x^2 - 6` can be represented as + * 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 + @@ -42,26 +38,28 @@ public data class ListPolynomial( * 0, // 0 x^4 * ) * ``` - * It is recommended not to put extra zeros at end of the list (as for `0x^3` and `0x^4` in the example), but is not - * prohibited. + * 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. */ public val coefficients: List ) : Polynomial { - override fun toString(): String = "Polynomial$coefficients" + override fun toString(): String = "ListPolynomial$coefficients" } /** - * Space of univariate polynomials constructed over ring. + * Arithmetic context for univariate polynomials with coefficients stored as a [List] constructed with the given [ring] + * of constants. * - * @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 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 polynomial. + * 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]. */ @@ -79,7 +77,7 @@ public open class ListPolynomialSpace>( } ) /** - * Returns difference between the polynomial and the integer represented as polynomial. + * 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]. */ @@ -97,7 +95,7 @@ public open class ListPolynomialSpace>( } ) /** - * Returns product of the polynomial and the integer represented as polynomial. + * Returns product of the polynomial and the integer represented as a polynomial. * * The operation is equivalent to sum of [other] copies of [this]. */ @@ -112,7 +110,7 @@ public open class ListPolynomialSpace>( ) /** - * Returns sum of the integer represented as polynomial and the polynomial. + * 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]. */ @@ -130,7 +128,7 @@ public open class ListPolynomialSpace>( } ) /** - * Returns difference between the integer represented as polynomial and the polynomial. + * 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]. */ @@ -150,7 +148,7 @@ public open class ListPolynomialSpace>( } ) /** - * Returns product of the integer represented as polynomial and the polynomial. + * Returns product of the integer represented as a polynomial and the polynomial. * * The operation is equivalent to sum of [this] copies of [other]. */ @@ -170,7 +168,7 @@ public open class ListPolynomialSpace>( public override fun number(value: Int): ListPolynomial = number(constantNumber(value)) /** - * Returns sum of the constant represented as polynomial and the polynomial. + * Returns sum of the constant represented as a polynomial and the polynomial. */ public override operator fun C.plus(other: ListPolynomial): ListPolynomial = with(other.coefficients) { @@ -186,7 +184,7 @@ public open class ListPolynomialSpace>( ) } /** - * Returns difference between the constant represented as polynomial and the polynomial. + * Returns difference between the constant represented as a polynomial and the polynomial. */ public override operator fun C.minus(other: ListPolynomial): ListPolynomial = with(other.coefficients) { @@ -204,7 +202,7 @@ public open class ListPolynomialSpace>( ) } /** - * Returns product of the constant represented as polynomial and the polynomial. + * Returns product of the constant represented as a polynomial and the polynomial. */ public override operator fun C.times(other: ListPolynomial): ListPolynomial = ListPolynomial( @@ -216,7 +214,7 @@ public open class ListPolynomialSpace>( ) /** - * Returns sum of the constant represented as polynomial and the polynomial. + * Returns sum of the constant represented as a polynomial and the polynomial. */ public override operator fun ListPolynomial.plus(other: C): ListPolynomial = with(coefficients) { @@ -232,7 +230,7 @@ public open class ListPolynomialSpace>( ) } /** - * Returns difference between the constant represented as polynomial and the polynomial. + * Returns difference between the constant represented as a polynomial and the polynomial. */ public override operator fun ListPolynomial.minus(other: C): ListPolynomial = with(coefficients) { @@ -248,7 +246,7 @@ public open class ListPolynomialSpace>( ) } /** - * Returns product of the constant represented as polynomial and the polynomial. + * Returns product of the constant represented as a polynomial and the polynomial. */ public override operator fun ListPolynomial.times(other: C): ListPolynomial = ListPolynomial( @@ -262,7 +260,7 @@ public open class ListPolynomialSpace>( /** * Converts the constant [value] to polynomial. */ - public override fun number(value: C): ListPolynomial = ListPolynomial(value) + public override fun number(value: C): ListPolynomial = ListPolynomial(listOf(value)) /** * Returns negation of the polynomial. @@ -321,9 +319,9 @@ public open class ListPolynomialSpace>( */ override val zero: ListPolynomial = ListPolynomial(emptyList()) /** - * Instance of unit constant (unit of the underlying ring). + * Instance of unit polynomial (unit of the polynomial ring). */ - override val one: ListPolynomial = ListPolynomial(listOf(constantOne)) + 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 @@ -331,23 +329,43 @@ public open class ListPolynomialSpace>( */ 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. + */ @Suppress("NOTHING_TO_INLINE") public inline fun ListPolynomial.substitute(argument: C): C = this.substitute(ring, argument) + /** + * Substitutes provided polynomial [argument] into [this] polynomial. + */ @Suppress("NOTHING_TO_INLINE") public inline fun ListPolynomial.substitute(argument: ListPolynomial): ListPolynomial = this.substitute(ring, argument) + /** + * Represent [this] polynomial as a regular context-less function. + */ @Suppress("NOTHING_TO_INLINE") public inline fun ListPolynomial.asFunction(): (C) -> C = { this.substitute(ring, it) } + /** + * Represent [this] polynomial as a regular context-less function. + */ @Suppress("NOTHING_TO_INLINE") - public inline fun ListPolynomial.asFunctionOnConstants(): (C) -> C = { this.substitute(ring, it) } + public inline fun ListPolynomial.asFunctionOfConstant(): (C) -> C = { this.substitute(ring, it) } + /** + * Represent [this] polynomial as a regular context-less function. + */ @Suppress("NOTHING_TO_INLINE") - public inline fun ListPolynomial.asFunctionOnPolynomials(): (ListPolynomial) -> ListPolynomial = { this.substitute(ring, it) } + public inline fun ListPolynomial.asFunctionOfPolynomial(): (ListPolynomial) -> ListPolynomial = { this.substitute(ring, it) } /** - * Evaluates the polynomial for the given value [argument]. + * Evaluates value of [this] polynomial on provided [argument]. */ @Suppress("NOTHING_TO_INLINE") public inline operator fun ListPolynomial.invoke(argument: C): C = this.substitute(ring, argument) + /** + * Evaluates value of [this] polynomial on provided [argument]. + */ @Suppress("NOTHING_TO_INLINE") public inline operator fun ListPolynomial.invoke(argument: ListPolynomial): ListPolynomial = this.substitute(ring, argument) } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt index 7b6c23ac3..f3e352bcd 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt @@ -8,13 +8,23 @@ package space.kscience.kmath.functions import space.kscience.kmath.operations.Ring +/** + * Represents 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 = "RationalFunction${numerator.coefficients}/${denominator.coefficients}" + 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, ) : @@ -30,76 +40,98 @@ public class ListRationalFunctionSpace> ( 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 /** - * Instance of zero rational function (zero of the rational functions ring). + * Evaluates value of [this] polynomial on provided argument. */ - public override val zero: ListRationalFunction = ListRationalFunction(polynomialZero, polynomialOne) + @Suppress("NOTHING_TO_INLINE") + public inline fun ListPolynomial.substitute(argument: C): C = this.substitute(ring, argument) /** - * Instance of unit polynomial (unit of the rational functions ring). + * Substitutes provided polynomial [argument] into [this] polynomial. */ - public override val one: ListRationalFunction = ListRationalFunction(polynomialOne, polynomialOne) + @Suppress("NOTHING_TO_INLINE") + public inline fun ListPolynomial.substitute(argument: ListPolynomial): ListPolynomial = this.substitute(ring, argument) + /** + * Substitutes provided rational function [argument] into [this] polynomial. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun ListPolynomial.substitute(argument: ListRationalFunction): ListRationalFunction = this.substitute(ring, argument) + /** + * Substitutes provided polynomial [argument] into [this] rational function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun ListRationalFunction.substitute(argument: ListPolynomial): ListRationalFunction = this.substitute(ring, argument) + /** + * Substitutes provided rational function [argument] into [this] rational function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun ListRationalFunction.substitute(argument: ListRationalFunction): ListRationalFunction = this.substitute(ring, argument) - // TODO: Разобрать + /** + * Represent [this] polynomial as a regular context-less function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun ListPolynomial.asFunction(): (C) -> C = { this.substitute(ring, it) } + /** + * Represent [this] polynomial as a regular context-less function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun ListPolynomial.asFunctionOfConstant(): (C) -> C = { this.substitute(ring, it) } + /** + * Represent [this] polynomial as a regular context-less function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun ListPolynomial.asFunctionOfPolynomial(): (ListPolynomial) -> ListPolynomial = { this.substitute(ring, it) } + /** + * Represent [this] polynomial as a regular context-less function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun ListPolynomial.asFunctionOfRationalFunction(): (ListRationalFunction) -> ListRationalFunction = { this.substitute(ring, it) } + /** + * Represent [this] rational function as a regular context-less function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun ListRationalFunction.asFunctionOfPolynomial(): (ListPolynomial) -> ListRationalFunction = { this.substitute(ring, it) } + /** + * Represent [this] rational function as a regular context-less function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun ListRationalFunction.asFunctionOfRationalFunction(): (ListRationalFunction) -> ListRationalFunction = { this.substitute(ring, it) } -// operator fun invoke(arg: UnivariatePolynomial): RationalFunction = -// RationalFunction( -// numerator(arg), -// denominator(arg) -// ) -// -// operator fun invoke(arg: RationalFunction): RationalFunction { -// val num = numerator invokeRFTakeNumerator arg -// val den = denominator invokeRFTakeNumerator arg -// val degreeDif = numeratorDegree - denominatorDegree -// return if (degreeDif > 0) -// RationalFunction( -// num, -// multiplyByPower(den, arg.denominator, degreeDif) -// ) -// else -// RationalFunction( -// multiplyByPower(num, arg.denominator, -degreeDif), -// den -// ) -// } -// -// override fun toString(): String = toString(UnivariatePolynomial.variableName) -// -// fun toString(withVariableName: String = UnivariatePolynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toString(withVariableName) -// else -> "${numerator.toStringWithBrackets(withVariableName)}/${denominator.toStringWithBrackets(withVariableName)}" -// } -// -// fun toStringWithBrackets(withVariableName: String = UnivariatePolynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toStringWithBrackets(withVariableName) -// else -> "(${numerator.toStringWithBrackets(withVariableName)}/${denominator.toStringWithBrackets(withVariableName)})" -// } -// -// fun toReversedString(withVariableName: String = UnivariatePolynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedString(withVariableName) -// else -> "${numerator.toReversedStringWithBrackets(withVariableName)}/${denominator.toReversedStringWithBrackets(withVariableName)}" -// } -// -// fun toReversedStringWithBrackets(withVariableName: String = UnivariatePolynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedStringWithBrackets(withVariableName) -// else -> "(${numerator.toReversedStringWithBrackets(withVariableName)}/${denominator.toReversedStringWithBrackets(withVariableName)})" -// } -// -// fun removeZeros() = -// RationalFunction( -// numerator.removeZeros(), -// denominator.removeZeros() -// ) + /** + * Evaluates value of [this] polynomial on provided argument. + */ + @Suppress("NOTHING_TO_INLINE") + public inline operator fun ListPolynomial.invoke(argument: C): C = this.substitute(ring, argument) + /** + * Evaluates value of [this] polynomial on provided argument. + */ + @Suppress("NOTHING_TO_INLINE") + public inline operator fun ListPolynomial.invoke(argument: ListPolynomial): ListPolynomial = this.substitute(ring, argument) + /** + * Evaluates value of [this] polynomial on provided argument. + */ + @Suppress("NOTHING_TO_INLINE") + public inline operator fun ListPolynomial.invoke(argument: ListRationalFunction): ListRationalFunction = this.substitute(ring, argument) + /** + * Evaluates value of [this] rational function on provided argument. + */ + @Suppress("NOTHING_TO_INLINE") + public inline operator fun ListRationalFunction.invoke(argument: ListPolynomial): ListRationalFunction = this.substitute(ring, argument) + /** + * Evaluates value of [this] rational function on provided argument. + */ + @Suppress("NOTHING_TO_INLINE") + public inline operator fun ListRationalFunction.invoke(argument: ListRationalFunction): ListRationalFunction = this.substitute(ring, argument) } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt deleted file mode 100644 index e75373819..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.operations.invoke -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.ScaleOperations -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract -import kotlin.experimental.ExperimentalTypeInference -import kotlin.jvm.JvmName -import kotlin.math.max - - -/** - * Polynomial model without fixation on specific context they are applied to. - * - * @param C the type of constants. - */ -public data class NumberedPolynomial -internal constructor( - /** - * Map that collects coefficients of the polynomial. Every monomial `a x_1^{d_1} ... x_n^{d_n}` is represented as - * pair "key-value" in the map, where value is coefficients `a` and - * key is list that associates index of every variable in the monomial with multiplicity of the variable occurring - * in the monomial. For example coefficients of polynomial `5 x_1^2 x_3^3 - 6 x_2` can be represented as - * ``` - * mapOf( - * listOf(2, 0, 3) to 5, - * listOf(0, 1) to (-6), - * ) - * ``` - * and also as - * ``` - * mapOf( - * listOf(2, 0, 3) to 5, - * listOf(0, 1) to (-6), - * listOf(0, 1, 1) to 0, - * ) - * ``` - * It is recommended not to put zero monomials into the map, but is not prohibited. Lists of degrees always do not - * contain any zeros on end, but can contain zeros on start or anywhere in middle. - */ - public val coefficients: Map, C> -) : Polynomial { - override fun toString(): String = "NumberedPolynomial$coefficients" -} - -/** - * Space of polynomials. - * - * @param C the type of operated polynomials. - * @param A the intersection of [Ring] of [C] and [ScaleOperations] of [C]. - * @param ring the [A] instance. - */ -public open class NumberedPolynomialSpace>( - public final override val ring: A, -) : PolynomialSpaceOverRing, A> { - /** - * Returns sum of the polynomial and the integer represented as 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 - NumberedPolynomial( - coefficients - .toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = getOrElse(degs) { constantZero } + other - } - ) - /** - * Returns difference between the polynomial and the integer represented as 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 - NumberedPolynomial( - coefficients - .toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = getOrElse(degs) { constantZero } - other - } - ) - /** - * Returns product of the polynomial and the integer represented as polynomial. - * - * The operation is equivalent to sum of [other] copies of [this]. - */ - public override operator fun NumberedPolynomial.times(other: Int): NumberedPolynomial = - if (other == 0) zero - else NumberedPolynomial( - coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this[degs]!! * other - } - ) - - /** - * Returns sum of the integer represented as 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 - NumberedPolynomial( - other.coefficients - .toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = this@plus + getOrElse(degs) { constantZero } - } - ) - /** - * Returns difference between the integer represented as 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 = - if (this == 0) other - else - NumberedPolynomial( - other.coefficients - .toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = this@minus - getOrElse(degs) { constantZero } - } - ) - /** - * Returns product of the integer represented as polynomial and the polynomial. - * - * The operation is equivalent to sum of [this] copies of [other]. - */ - public override operator fun Int.times(other: NumberedPolynomial): NumberedPolynomial = - if (this == 0) zero - else NumberedPolynomial( - other.coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this@times * this[degs]!! - } - ) - - /** - * Converts the integer [value] to polynomial. - */ - public override fun number(value: Int): NumberedPolynomial = number(constantNumber(value)) - - /** - * Returns sum of the constant represented as polynomial and the polynomial. - */ - override operator fun C.plus(other: NumberedPolynomial): NumberedPolynomial = - with(other.coefficients) { - if (isEmpty()) NumberedPolynomial(mapOf(emptyList() to this@plus)) - else NumberedPolynomial( - toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = this@plus + getOrElse(degs) { constantZero } - } - ) - } - /** - * Returns difference between the constant represented as polynomial and the polynomial. - */ - override operator fun C.minus(other: NumberedPolynomial): NumberedPolynomial = - with(other.coefficients) { - if (isEmpty()) NumberedPolynomial(mapOf(emptyList() to this@minus)) - else NumberedPolynomial( - toMutableMap() - .apply { - forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } - - val degs = emptyList() - - this[degs] = this@minus - getOrElse(degs) { constantZero } - } - ) - } - /** - * Returns product of the constant represented as polynomial and the polynomial. - */ - override operator fun C.times(other: NumberedPolynomial): NumberedPolynomial = - NumberedPolynomial( - other.coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this@times * this[degs]!! - } - ) - - /** - * Returns sum of the constant represented as polynomial and the polynomial. - */ - override operator fun NumberedPolynomial.plus(other: C): NumberedPolynomial = - with(coefficients) { - if (isEmpty()) NumberedPolynomial(mapOf(emptyList() to other)) - else NumberedPolynomial( - toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = getOrElse(degs) { constantZero } + other - } - ) - } - /** - * Returns difference between the constant represented as polynomial and the polynomial. - */ - override operator fun NumberedPolynomial.minus(other: C): NumberedPolynomial = - with(coefficients) { - if (isEmpty()) NumberedPolynomial(mapOf(emptyList() to other)) - else NumberedPolynomial( - toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = getOrElse(degs) { constantZero } - other - } - ) - } - /** - * Returns product of the constant represented as polynomial and the polynomial. - */ - override operator fun NumberedPolynomial.times(other: C): NumberedPolynomial = - NumberedPolynomial( - coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this[degs]!! * other - } - ) - - /** - * Converts the constant [value] to polynomial. - */ - public override fun number(value: C): NumberedPolynomial = - NumberedPolynomial(mapOf(emptyList() to value)) - - /** - * Returns negation of the polynomial. - */ - override fun NumberedPolynomial.unaryMinus(): NumberedPolynomial = - NumberedPolynomial( - coefficients.mapValues { -it.value } - ) - /** - * Returns sum of the polynomials. - */ - override operator fun NumberedPolynomial.plus(other: NumberedPolynomial): NumberedPolynomial = - NumberedPolynomial( - buildMap(coefficients.size + other.coefficients.size) { - other.coefficients.mapValuesTo(this) { it.value } - other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value } - } - ) - /** - * Returns difference of the polynomials. - */ - override operator fun NumberedPolynomial.minus(other: NumberedPolynomial): NumberedPolynomial = - NumberedPolynomial( - buildMap(coefficients.size + other.coefficients.size) { - other.coefficients.mapValuesTo(this) { it.value } - other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value } - } - ) - /** - * Returns product of the polynomials. - */ - override operator fun NumberedPolynomial.times(other: NumberedPolynomial): NumberedPolynomial = - NumberedPolynomial( - 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 - this[degs] = if (degs in this) this[degs]!! + c else c - } - } - ) - - /** - * Instance of zero polynomial (zero of the polynomial ring). - */ - override val zero: NumberedPolynomial = NumberedPolynomial(emptyMap()) - /** - * Instance of unit polynomial (unit of the polynomial ring). - */ - override val one: NumberedPolynomial = - NumberedPolynomial( - mapOf( - emptyList() to constantOne // 1 * x_1^0 * x_2^0 * ... - ) - ) - - /** - * 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.entries.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.entries.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.entries.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.entries.maxOfOrNull { (degs, _) -> degs.getOrElse(variable) { 0u } } ?: 0u - /** - * Counts degree of the polynomial by the specified [variables]. - */ - public fun NumberedPolynomial.degreeBy(variables: Collection): UInt = - coefficients.entries.maxOfOrNull { (degs, _) -> - degs.withIndex().filter { (index, _) -> index in variables }.sumOf { it.value } - } ?: 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 } - - @Suppress("NOTHING_TO_INLINE") - public inline fun NumberedPolynomial.substitute(argument: Map): NumberedPolynomial = this.substitute(ring, argument) - @Suppress("NOTHING_TO_INLINE") - @JvmName("substitutePolynomial") - public inline fun NumberedPolynomial.substitute(argument: Map>): NumberedPolynomial = this.substitute(ring, argument) - - @Suppress("NOTHING_TO_INLINE") - public inline fun NumberedPolynomial.asFunction(): (Map) -> NumberedPolynomial = { this.substitute(ring, it) } - @Suppress("NOTHING_TO_INLINE") - public inline fun NumberedPolynomial.asFunctionOnConstants(): (Map) -> NumberedPolynomial = { this.substitute(ring, it) } - @Suppress("NOTHING_TO_INLINE") - public inline fun NumberedPolynomial.asFunctionOnPolynomials(): (Map>) -> NumberedPolynomial = { this.substitute(ring, it) } - - @Suppress("NOTHING_TO_INLINE") - public inline operator fun NumberedPolynomial.invoke(argument: Map): NumberedPolynomial = this.substitute(ring, argument) - @Suppress("NOTHING_TO_INLINE") - @JvmName("invokePolynomial") - public inline operator fun NumberedPolynomial.invoke(argument: Map>): NumberedPolynomial = this.substitute(ring, argument) - - // FIXME: Move to other constructors with context receiver - public fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(emptyList() to this)) -} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt deleted file mode 100644 index 30c7f0188..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.invoke -import kotlin.math.max - - -public class NumberedRationalFunction internal constructor( - public override val numerator: NumberedPolynomial, - public override val denominator: NumberedPolynomial -) : RationalFunction> { - override fun toString(): String = "NumberedRationalFunction${numerator.coefficients}/${denominator.coefficients}" -} - -public class NumberedRationalFunctionSpace> ( - public val ring: A, -) : - RationalFunctionalSpaceOverPolynomialSpace< - C, - NumberedPolynomial, - NumberedRationalFunction, - NumberedPolynomialSpace, - >, - PolynomialSpaceOfFractions< - C, - NumberedPolynomial, - NumberedRationalFunction, - >() { - - override val polynomialRing : NumberedPolynomialSpace = NumberedPolynomialSpace(ring) - override fun constructRationalFunction( - numerator: NumberedPolynomial, - denominator: NumberedPolynomial - ): NumberedRationalFunction = - NumberedRationalFunction(numerator, denominator) - - /** - * Instance of zero rational function (zero of the rational functions ring). - */ - public override val zero: NumberedRationalFunction = NumberedRationalFunction(polynomialZero, polynomialOne) - /** - * Instance of unit polynomial (unit of the rational functions ring). - */ - public override val one: NumberedRationalFunction = NumberedRationalFunction(polynomialOne, polynomialOne) - - /** - * 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: Разобрать - -// operator fun invoke(arg: Map): NumberedRationalFunction = -// NumberedRationalFunction( -// numerator(arg), -// denominator(arg) -// ) -// -// @JvmName("invokePolynomial") -// operator fun invoke(arg: Map>): NumberedRationalFunction = -// NumberedRationalFunction( -// numerator(arg), -// denominator(arg) -// ) -// -// @JvmName("invokeRationalFunction") -// operator fun invoke(arg: Map>): NumberedRationalFunction { -// var num = numerator invokeRFTakeNumerator arg -// var den = denominator invokeRFTakeNumerator arg -// for (variable in 0 until max(numerator.countOfVariables, denominator.countOfVariables)) if (variable in arg) { -// val degreeDif = numerator.degrees.getOrElse(variable) { 0 } - denominator.degrees.getOrElse(variable) { 0 } -// if (degreeDif > 0) -// den = multiplyByPower(den, arg[variable]!!.denominator, degreeDif) -// else -// num = multiplyByPower(num, arg[variable]!!.denominator, -degreeDif) -// } -// return NumberedRationalFunction(num, den) -// } -// -// override fun toString(): String = toString(Polynomial.variableName) -// -// fun toString(withVariableName: String = Polynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toString(withVariableName) -// else -> "${numerator.toStringWithBrackets(withVariableName)}/${denominator.toStringWithBrackets(withVariableName)}" -// } -// -// fun toString(namer: (Int) -> String): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toString(namer) -// else -> "${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)}" -// } -// -// fun toStringWithBrackets(withVariableName: String = Polynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toStringWithBrackets(withVariableName) -// else -> "(${numerator.toStringWithBrackets(withVariableName)}/${denominator.toStringWithBrackets(withVariableName)})" -// } -// -// fun toStringWithBrackets(namer: (Int) -> String): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toStringWithBrackets(namer) -// else -> "(${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)})" -// } -// -// fun toReversedString(withVariableName: String = Polynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedString(withVariableName) -// else -> "${numerator.toReversedStringWithBrackets(withVariableName)}/${denominator.toReversedStringWithBrackets(withVariableName)}" -// } -// -// fun toReversedString(namer: (Int) -> String): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedString(namer) -// else -> "${numerator.toReversedStringWithBrackets(namer)}/${denominator.toReversedStringWithBrackets(namer)}" -// } -// -// fun toReversedStringWithBrackets(withVariableName: String = Polynomial.variableName): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedStringWithBrackets(withVariableName) -// else -> "(${numerator.toReversedStringWithBrackets(withVariableName)}/${denominator.toReversedStringWithBrackets(withVariableName)})" -// } -// -// fun toReversedStringWithBrackets(namer: (Int) -> String): String = -// when(true) { -// numerator.isZero() -> "0" -// denominator.isOne() -> numerator.toReversedStringWithBrackets(namer) -// else -> "(${numerator.toReversedStringWithBrackets(namer)}/${denominator.toReversedStringWithBrackets(namer)})" -// } -} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index e201f1f6e..12490d133 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -25,38 +25,38 @@ public interface Polynomial @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 constant (member of underlying 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]. */ public operator fun C.plus(other: Int): C /** - * Returns difference between the constant and the integer represented as constant (member of underlying ring). + * 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]. */ public operator fun C.minus(other: Int): C /** - * Returns product of the constant and the integer represented as constant (member of underlying ring). + * 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]. */ public operator fun C.times(other: Int): C /** - * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public operator fun Int.plus(other: C): C /** - * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public operator fun Int.minus(other: C): C /** - * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ @@ -72,38 +72,38 @@ public interface PolynomialSpace> : Ring

{ public fun Int.asConstant(): C = constantNumber(this) /** - * Returns sum of the polynomial and the integer represented as polynomial. + * 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 polynomial. + * 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 polynomial. + * 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 polynomial and the polynomial. + * 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 polynomial and the polynomial. + * 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 polynomial and the polynomial. + * Returns product of the integer represented as a polynomial and the polynomial. * * The operation is equivalent to sum of [this] copies of [other]. */ @@ -165,28 +165,28 @@ public interface PolynomialSpace> : Ring

{ public val constantOne: C /** - * Returns sum of the constant represented as polynomial and the polynomial. + * Returns sum of the constant represented as a polynomial and the polynomial. */ public operator fun C.plus(other: P): P /** - * Returns difference between the constant represented as polynomial and the polynomial. + * Returns difference between the constant represented as a polynomial and the polynomial. */ public operator fun C.minus(other: P): P /** - * Returns product of the constant represented as polynomial and the polynomial. + * Returns product of the constant represented as a polynomial and the polynomial. */ public operator fun C.times(other: P): P /** - * Returns sum of the constant represented as polynomial and the polynomial. + * Returns sum of the constant represented as a polynomial and the polynomial. */ public operator fun P.plus(other: C): P /** - * Returns difference between the constant represented as polynomial and the polynomial. + * Returns difference between the constant represented as a polynomial and the polynomial. */ public operator fun P.minus(other: C): P /** - * Returns product of the constant represented as polynomial and the polynomial. + * Returns product of the constant represented as a polynomial and the polynomial. */ public operator fun P.times(other: C): P @@ -254,41 +254,44 @@ public interface PolynomialSpace> : Ring

{ @Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 public interface PolynomialSpaceOverRing, A: Ring> : 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 constant (member of underlying 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]. */ 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 constant (member of underlying ring). + * 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]. */ 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 constant (member of underlying ring). + * 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]. */ public override operator fun C.times(other: Int): C = ring { multiplyByDoubling(this@times, other) } /** - * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public override operator fun Int.plus(other: C): C = ring { addMultipliedByDoubling(other, one, this@plus) } /** - * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public override operator fun Int.minus(other: C): C = ring { addMultipliedByDoubling(-other, one, this@minus) } /** - * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ @@ -330,58 +333,145 @@ public interface PolynomialSpaceOverRing, A: Ring> : Poly 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") 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") 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") 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") 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") 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") public operator fun Int.times(other: V): P - @JvmName("plusConstantVariable") - public operator fun C.plus(other: V): P - @JvmName("minusConstantVariable") - public operator fun C.minus(other: V): P - @JvmName("timesConstantVariable") - public operator fun C.times(other: V): P - + /** + * Returns sum of the variable represented as a monic monomial and the constant represented as a constant polynomial. + */ @JvmName("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") 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") 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") + 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") + 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") + 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 diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index dfec126f3..01911f980 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -25,44 +25,44 @@ public interface RationalFunction> { * [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 in them. + * @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 RationalFunctionalSpace, R: RationalFunction> : Ring { /** - * Returns sum of the constant and the integer represented as constant (member of underlying 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]. */ public operator fun C.plus(other: Int): C /** - * Returns difference between the constant and the integer represented as constant (member of underlying ring). + * 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]. */ public operator fun C.minus(other: Int): C /** - * Returns product of the constant and the integer represented as constant (member of underlying ring). + * 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]. */ public operator fun C.times(other: Int): C /** - * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public operator fun Int.plus(other: C): C /** - * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public operator fun Int.minus(other: C): C /** - * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ @@ -78,38 +78,38 @@ public interface RationalFunctionalSpace, R: RationalFunctio public fun Int.asConstant(): C = constantNumber(this) /** - * Returns sum of the constant and the integer represented as polynomial. + * 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]. */ public operator fun P.plus(other: Int): P /** - * Returns difference between the constant and the integer represented as polynomial. + * 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]. */ public operator fun P.minus(other: Int): P /** - * Returns product of the constant and the integer represented as polynomial. + * Returns product of the constant 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 /** - * Returns sum of the integer represented as polynomial and the constant. + * 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]. */ public operator fun Int.plus(other: P): P /** - * Returns difference between the integer represented as polynomial and the constant. + * 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]. */ public operator fun Int.minus(other: P): P /** - * Returns product of the integer represented as polynomial and the constant. + * Returns product of the integer represented as a polynomial and the constant. * * The operation is equivalent to sum of [this] copies of [other]. */ @@ -125,25 +125,25 @@ public interface RationalFunctionalSpace, R: RationalFunctio public fun Int.asPolynomial(): P = polynomialNumber(this) /** - * Returns sum of the rational function and the integer represented as rational function. + * 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 rational function. + * 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 rational function. + * 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 rational function. + * 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]. @@ -151,25 +151,25 @@ public interface RationalFunctionalSpace, R: RationalFunctio public operator fun R.div(other: Int): R = this / multiplyByDoubling(one, other) /** - * Returns sum of the integer represented as rational function and the rational function. + * 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 rational function and the rational function. + * 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 rational function and the rational function. + * 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 rational function and the rational function. + * 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. @@ -232,28 +232,28 @@ public interface RationalFunctionalSpace, R: RationalFunctio public val constantOne: C /** - * Returns sum of the constant represented as polynomial and the polynomial. + * Returns sum of the constant represented as a polynomial and the polynomial. */ public operator fun C.plus(other: P): P /** - * Returns difference between the constant represented as polynomial and the polynomial. + * Returns difference between the constant represented as a polynomial and the polynomial. */ public operator fun C.minus(other: P): P /** - * Returns product of the constant represented as polynomial and the polynomial. + * Returns product of the constant represented as a polynomial and the polynomial. */ public operator fun C.times(other: P): P /** - * Returns sum of the constant represented as polynomial and the polynomial. + * Returns sum of the constant represented as a polynomial and the polynomial. */ public operator fun P.plus(other: C): P /** - * Returns difference between the constant represented as polynomial and the polynomial. + * Returns difference between the constant represented as a polynomial and the polynomial. */ public operator fun P.minus(other: C): P /** - * Returns product of the constant represented as polynomial and the polynomial. + * Returns product of the constant represented as a polynomial and the polynomial. */ public operator fun P.times(other: C): P @@ -305,36 +305,36 @@ public interface RationalFunctionalSpace, R: RationalFunctio public val polynomialOne: P /** - * Returns sum of the constant represented as rational function and the rational function. + * Returns sum of the constant represented as a rational function and the rational function. */ public operator fun C.plus(other: R): R /** - * Returns difference between the constant represented as polynomial and the rational function. + * Returns difference between the constant represented as a polynomial and the rational function. */ public operator fun C.minus(other: R): R /** - * Returns product of the constant represented as polynomial and the rational function. + * Returns product of the constant represented as a polynomial and the rational function. */ public operator fun C.times(other: R): R /** - * Returns quotient of the constant represented as polynomial and the rational function. + * Returns quotient of the constant represented as a polynomial and the rational function. */ public operator fun C.div(other: R): R /** - * Returns sum of the rational function and the constant represented as rational function. + * Returns sum of the rational function and the constant represented as a rational function. */ public operator fun R.plus(other: C): R /** - * Returns difference between the rational function and the constant represented as rational function. + * Returns difference between the rational function and the constant represented as a rational function. */ public operator fun R.minus(other: C): R /** - * Returns product of the rational function and the constant represented as rational function. + * Returns product of the rational function and the constant represented as a rational function. */ public operator fun R.times(other: C): R /** - * Returns quotient of the rational function and the constant represented as rational function. + * Returns quotient of the rational function and the constant represented as a rational function. */ public operator fun R.div(other: C): R @@ -348,36 +348,36 @@ public interface RationalFunctionalSpace, R: RationalFunctio public fun C.asRationalFunction(): R = number(this) /** - * Returns sum of the polynomial represented as rational function and the rational function. + * Returns sum of the polynomial represented as a rational function and the rational function. */ public operator fun P.plus(other: R): R /** - * Returns difference between the polynomial represented as polynomial and the rational function. + * Returns difference between the polynomial represented as a polynomial and the rational function. */ public operator fun P.minus(other: R): R /** - * Returns product of the polynomial represented as polynomial and the rational function. + * Returns product of the polynomial represented as a polynomial and the rational function. */ public operator fun P.times(other: R): R /** - * Returns quotient of the polynomial represented as polynomial and the rational function. + * Returns quotient of the polynomial represented as a polynomial and the rational function. */ public operator fun P.div(other: R): R /** - * Returns sum of the rational function and the polynomial represented as rational function. + * Returns sum of the rational function and the polynomial represented as a rational function. */ public operator fun R.plus(other: P): R /** - * Returns difference between the rational function and the polynomial represented as rational function. + * Returns difference between the rational function and the polynomial represented as a rational function. */ public operator fun R.minus(other: P): R /** - * Returns product of the rational function and the polynomial represented as rational function. + * Returns product of the rational function and the polynomial represented as a rational function. */ public operator fun R.times(other: P): R /** - * Returns quotient of the rational function and the polynomial represented as rational function. + * Returns quotient of the rational function and the polynomial represented as a rational function. */ public operator fun R.div(other: P): R @@ -459,43 +459,51 @@ public interface RationalFunctionalSpace, R: RationalFunctio * @param A the type of algebraic structure (precisely, of ring) provided for constants. */ @Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 -public interface RationalFunctionalSpaceOverRing, R: RationalFunction, A: Ring> : RationalFunctionalSpace { +public interface RationalFunctionalSpaceOverRing< + C, + P: Polynomial, + R: RationalFunction, + A: Ring + > : RationalFunctionalSpace { + /** + * 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 constant (member of underlying 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]. */ 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 constant (member of underlying ring). + * 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]. */ 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 constant (member of underlying ring). + * 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]. */ public override operator fun C.times(other: Int): C = ring { multiplyByDoubling(this@times, other) } /** - * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public override operator fun Int.plus(other: C): C = ring { addMultipliedByDoubling(other, one, this@plus) } /** - * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public override operator fun Int.minus(other: C): C = ring { addMultipliedByDoubling(-other, one, this@minus) } /** - * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ @@ -560,41 +568,44 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< AP: PolynomialSpace, > : RationalFunctionalSpace { + /** + * 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 constant (member of underlying 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]. */ public override operator fun C.plus(other: Int): C = polynomialRing { this@plus + other } /** - * Returns difference between the constant and the integer represented as constant (member of underlying ring). + * 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]. */ public override operator fun C.minus(other: Int): C = polynomialRing { this@minus - other } /** - * Returns product of the constant and the integer represented as constant (member of underlying ring). + * 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]. */ public override operator fun C.times(other: Int): C = polynomialRing { this@times * other } /** - * Returns sum of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public override operator fun Int.plus(other: C): C = polynomialRing { this@plus + other } /** - * Returns difference between the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ public override operator fun Int.minus(other: C): C = polynomialRing { this@minus - other } /** - * Returns product of the integer represented as constant (member of underlying ring) and the constant. + * 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]. */ @@ -610,38 +621,38 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< override fun Int.asConstant(): C = polynomialRing { asConstant() } /** - * Returns sum of the constant and the integer represented as polynomial. + * 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]. */ public override operator fun P.plus(other: Int): P = polynomialRing { this@plus + other } /** - * Returns difference between the constant and the integer represented as polynomial. + * 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]. */ public override operator fun P.minus(other: Int): P = polynomialRing { this@minus - other } /** - * Returns product of the constant and the integer represented as polynomial. + * Returns product of the constant and the integer represented as a polynomial. * * The operation is equivalent to sum of [other] copies of [this]. */ public override operator fun P.times(other: Int): P = polynomialRing { this@times * other } /** - * Returns sum of the integer represented as polynomial and the constant. + * 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]. */ public override operator fun Int.plus(other: P): P = polynomialRing { this@plus + other } /** - * Returns difference between the integer represented as polynomial and the constant. + * 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]. */ public override operator fun Int.minus(other: P): P = polynomialRing { this@minus - other } /** - * Returns product of the integer represented as polynomial and the constant. + * Returns product of the integer represented as a polynomial and the constant. * * The operation is equivalent to sum of [this] copies of [other]. */ @@ -697,28 +708,28 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< public override val constantOne: C get() = polynomialRing.constantOne /** - * Returns sum of the constant represented as polynomial and the polynomial. + * Returns sum of the constant represented as a polynomial and the polynomial. */ public override operator fun C.plus(other: P): P = polynomialRing { this@plus + other } /** - * Returns difference between the constant represented as polynomial and the polynomial. + * Returns difference between the constant represented as a polynomial and the polynomial. */ public override operator fun C.minus(other: P): P = polynomialRing { this@minus - other } /** - * Returns product of the constant represented as polynomial and the polynomial. + * Returns product of the constant represented as a polynomial and the polynomial. */ public override operator fun C.times(other: P): P = polynomialRing { this@times * other } /** - * Returns sum of the constant represented as polynomial and the polynomial. + * Returns sum of the constant represented as a polynomial and the polynomial. */ public override operator fun P.plus(other: C): P = polynomialRing { this@plus + other } /** - * Returns difference between the constant represented as polynomial and the polynomial. + * Returns difference between the constant represented as a polynomial and the polynomial. */ public override operator fun P.minus(other: C): P = polynomialRing { this@minus - other } /** - * Returns product of the constant represented as polynomial and the polynomial. + * Returns product of the constant represented as a polynomial and the polynomial. */ public override operator fun P.times(other: C): P = polynomialRing { this@times * other } @@ -774,7 +785,8 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< /** * 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 + * [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. @@ -786,10 +798,14 @@ public abstract class PolynomialSpaceOfFractions< P: Polynomial, R: RationalFunction, > : RationalFunctionalSpace { + + /** + * 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 rational function. + * 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]. */ @@ -799,7 +815,7 @@ public abstract class PolynomialSpaceOfFractions< denominator ) /** - * Returns difference between the rational function and the integer represented as rational function. + * 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]. */ @@ -809,7 +825,7 @@ public abstract class PolynomialSpaceOfFractions< denominator ) /** - * Returns product of the rational function and the integer represented as rational function. + * 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]. */ @@ -818,7 +834,12 @@ public abstract class PolynomialSpaceOfFractions< 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, @@ -826,7 +847,7 @@ public abstract class PolynomialSpaceOfFractions< ) /** - * Returns sum of the integer represented as rational function and the rational function. + * 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]. */ @@ -836,7 +857,7 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) /** - * Returns difference between the integer represented as rational function and the rational function. + * 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]. */ @@ -846,7 +867,7 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) /** - * Returns product of the integer represented as rational function and the rational function. + * 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]. */ @@ -855,7 +876,12 @@ public abstract class PolynomialSpaceOfFractions< 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, @@ -873,7 +899,7 @@ public abstract class PolynomialSpaceOfFractions< public override operator fun P.div(other: P): R = constructRationalFunction(this, other) /** - * Returns sum of the constant represented as rational function and the rational function. + * Returns sum of the constant represented as a rational function and the rational function. */ public override operator fun C.plus(other: R): R = constructRationalFunction( @@ -881,7 +907,7 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) /** - * Returns difference between the constant represented as polynomial and the rational function. + * Returns difference between the constant represented as a polynomial and the rational function. */ public override operator fun C.minus(other: R): R = constructRationalFunction( @@ -889,14 +915,16 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) /** - * Returns product of the constant represented as polynomial and the rational function. + * Returns product of the constant represented as a polynomial and the rational function. */ 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. + */ public override operator fun C.div(other: R): R = constructRationalFunction( this * other.denominator, @@ -904,7 +932,7 @@ public abstract class PolynomialSpaceOfFractions< ) /** - * Returns sum of the constant represented as rational function and the rational function. + * Returns sum of the constant represented as a rational function and the rational function. */ public override operator fun R.plus(other: C): R = constructRationalFunction( @@ -912,7 +940,7 @@ public abstract class PolynomialSpaceOfFractions< denominator ) /** - * Returns difference between the constant represented as rational function and the rational function. + * Returns difference between the constant represented as a rational function and the rational function. */ public override operator fun R.minus(other: C): R = constructRationalFunction( @@ -920,14 +948,16 @@ public abstract class PolynomialSpaceOfFractions< denominator ) /** - * Returns product of the constant represented as rational function and the rational function. + * Returns product of the constant represented as a rational function and the rational function. */ 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. + */ public override operator fun R.div(other: C): R = constructRationalFunction( numerator, @@ -940,7 +970,7 @@ public abstract class PolynomialSpaceOfFractions< public override fun number(value: C): R = constructRationalFunction(polynomialNumber(value)) /** - * Returns sum of the polynomial represented as rational function and the rational function. + * Returns sum of the polynomial represented as a rational function and the rational function. */ public override operator fun P.plus(other: R): R = constructRationalFunction( @@ -948,7 +978,7 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) /** - * Returns difference between the polynomial represented as polynomial and the rational function. + * Returns difference between the polynomial represented as a polynomial and the rational function. */ public override operator fun P.minus(other: R): R = constructRationalFunction( @@ -956,14 +986,16 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) /** - * Returns product of the polynomial represented as polynomial and the rational function. + * Returns product of the polynomial represented as a polynomial and the rational function. */ 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. + */ public override operator fun P.div(other: R): R = constructRationalFunction( this * other.denominator, @@ -971,7 +1003,7 @@ public abstract class PolynomialSpaceOfFractions< ) /** - * Returns sum of the polynomial represented as rational function and the rational function. + * Returns sum of the polynomial represented as a rational function and the rational function. */ public override operator fun R.plus(other: P): R = constructRationalFunction( @@ -979,7 +1011,7 @@ public abstract class PolynomialSpaceOfFractions< denominator ) /** - * Returns difference between the polynomial represented as rational function and the rational function. + * Returns difference between the polynomial represented as a rational function and the rational function. */ public override operator fun R.minus(other: P): R = constructRationalFunction( @@ -987,14 +1019,16 @@ public abstract class PolynomialSpaceOfFractions< denominator ) /** - * Returns product of the polynomial represented as rational function and the rational function. + * Returns product of the polynomial represented as a rational function and the rational function. */ 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. + */ public override operator fun R.div(other: P): R = constructRationalFunction( numerator, @@ -1034,7 +1068,9 @@ public abstract class PolynomialSpaceOfFractions< 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, @@ -1044,14 +1080,23 @@ public abstract class PolynomialSpaceOfFractions< /** * Instance of zero rational function (zero of the rational functions ring). */ - public override val zero: R get() = constructRationalFunction(polynomialZero) + public override val zero: R by lazy { constructRationalFunction(polynomialZero) } /** * Instance of unit polynomial (unit of the rational functions ring). */ - public override val one: R get() = constructRationalFunction(polynomialOne) + 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 MultivariateRationalFunctionalSpace< C, @@ -1059,70 +1104,179 @@ public interface MultivariateRationalFunctionalSpace< P: Polynomial, R: RationalFunction >: RationalFunctionalSpace { + /** + * Returns sum of the variable represented as a monic monomial and the integer represented as a constant polynomial. + */ @JvmName("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") 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") 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") 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") 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") public operator fun Int.times(other: V): P - @JvmName("plusConstantVariable") - public operator fun C.plus(other: V): P - @JvmName("minusConstantVariable") - public operator fun C.minus(other: V): P - @JvmName("timesConstantVariable") - public operator fun C.times(other: V): P - + /** + * Returns sum of the variable represented as a monic monomial and the constant represented as a constant polynomial. + */ @JvmName("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") 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") 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") + 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") + 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") + 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("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") + public fun number(variable: V): R = number(polynomialNumber(variable)) + /** + * Represents the variable as a rational function. + */ + @JvmName("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 @@ -1161,22 +1315,17 @@ public interface MultivariateRationalFunctionalSpace< public val R.countOfVariables: Int get() = variables.size } -public interface MultivariateRationalFunctionalSpaceOverRing< - C, - V, - P: Polynomial, - R: RationalFunction, - A: Ring - > : RationalFunctionalSpaceOverRing, MultivariateRationalFunctionalSpace - -public interface MultivariateRationalFunctionalSpaceOverPolynomialSpace< - C, - V, - P: Polynomial, - R: RationalFunction, - AP: PolynomialSpace, - > : RationalFunctionalSpaceOverPolynomialSpace, MultivariateRationalFunctionalSpace - +/** + * 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 MultivariateRationalFunctionalSpaceOverMultivariatePolynomialSpace< C, @@ -1184,57 +1333,137 @@ public interface MultivariateRationalFunctionalSpaceOverMultivariatePolynomialSp P: Polynomial, R: RationalFunction, AP: MultivariatePolynomialSpace, - > : MultivariateRationalFunctionalSpaceOverPolynomialSpace { + > : RationalFunctionalSpaceOverPolynomialSpace, MultivariateRationalFunctionalSpace { + /** + * 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 } - @JvmName("plusConstantVariable") - public override operator fun C.plus(other: V): P = polynomialRing { this@plus + other } - @JvmName("minusConstantVariable") - public override operator fun C.minus(other: V): P = polynomialRing { this@minus - other } - @JvmName("timesConstantVariable") - public override operator fun C.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 } @@ -1264,6 +1493,16 @@ public interface MultivariateRationalFunctionalSpaceOverMultivariatePolynomialSp 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, @@ -1271,18 +1510,27 @@ public abstract class MultivariatePolynomialSpaceOfFractions< P: Polynomial, R: RationalFunction, > : MultivariateRationalFunctionalSpace, 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( @@ -1290,18 +1538,27 @@ public abstract class MultivariatePolynomialSpaceOfFractions< 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. + */ @JvmName("timesRationalVariable") public override operator fun R.times(other: V): R = constructRationalFunction( diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt deleted file mode 100644 index e81a9388e..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.Ring - - -/** - * Returns the same degrees' description of the monomial, but without zero degrees. - */ -internal fun Map.cleanUp() = filterValues { it > 0U } - -// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(coefs, toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(coefs, toCheckInput) -@Suppress("FunctionName") -internal fun > A.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial { - if (!toCheckInput) return LabeledPolynomial(coefs) - - val fixedCoefs = LinkedHashMap, C>(coefs.size) - - for (entry in coefs) { - val key = entry.key.cleanUp() - val value = entry.value - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return LabeledPolynomial(fixedCoefs) -} - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs, toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs, toCheckInput) -@Suppress("FunctionName") -internal fun > A.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial { - if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) - - val fixedCoefs = LinkedHashMap, C>(pairs.size) - - for (entry in pairs) { - val key = entry.first.cleanUp() - val value = entry.second - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return LabeledPolynomial(fixedCoefs) -} - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs = pairs, toCheckInput = toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs = pairs, toCheckInput = toCheckInput) -@Suppress("FunctionName") -internal fun > A.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial { - if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) - - val fixedCoefs = LinkedHashMap, C>(pairs.size) - - for (entry in pairs) { - val key = entry.first.cleanUp() - val value = entry.second - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return LabeledPolynomial(fixedCoefs) -} - -@Suppress("FunctionName") -public fun > A.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledPolynomialSpace.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) - -@Suppress("FunctionName") -public fun > A.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledPolynomialSpace.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) - -@Suppress("FunctionName") -public fun > A.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledPolynomialSpace.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) - -//context(A) -//public fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to one)) -//context(LabeledPolynomialSpace) -//public fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to constantOne)) -//context(LabeledRationalFunctionSpace) -//public fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to constantOne)) - -public fun C.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to this)) - -@DslMarker -@UnstableKMathAPI -internal annotation class LabeledPolynomialConstructorDSL - -@UnstableKMathAPI -@LabeledPolynomialConstructorDSL -public class LabeledPolynomialTermSignatureBuilder { - private val signature: MutableMap = LinkedHashMap() - public fun build(): Map = signature - public infix fun Symbol.inPowerOf(deg: UInt) { - signature[this] = deg - } - @Suppress("NOTHING_TO_INLINE") - public inline infix fun Symbol.pow(deg: UInt): Unit = this inPowerOf deg - @Suppress("NOTHING_TO_INLINE") - public inline infix fun Symbol.`in`(deg: UInt): Unit = this inPowerOf deg - @Suppress("NOTHING_TO_INLINE") - public inline infix fun Symbol.of(deg: UInt): Unit = this inPowerOf deg -} - -@UnstableKMathAPI -public class LabeledPolynomialBuilder(private val zero: C, private val add: (C, C) -> C, capacity: Int = 0) { - private val coefficients: MutableMap, C> = LinkedHashMap(capacity) - public fun build(): LabeledPolynomial = LabeledPolynomial(coefficients) - public operator fun C.invoke(block: LabeledPolynomialTermSignatureBuilder.() -> Unit) { - val signature = LabeledPolynomialTermSignatureBuilder().apply(block).build() - coefficients[signature] = add(coefficients.getOrElse(signature) { zero }, this@invoke) - } - @Suppress("NOTHING_TO_INLINE") - public inline infix fun C.with(noinline block: LabeledPolynomialTermSignatureBuilder.() -> Unit): Unit = this.invoke(block) - @Suppress("NOTHING_TO_INLINE") - public inline infix fun (LabeledPolynomialTermSignatureBuilder.() -> Unit).with(coef: C): Unit = coef.invoke(this) - @Suppress("NOTHING_TO_INLINE") - public infix fun sig(block: LabeledPolynomialTermSignatureBuilder.() -> Unit): LabeledPolynomialTermSignatureBuilder.() -> Unit = block -} - -// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available - -@UnstableKMathAPI -@LabeledPolynomialConstructorDSL -@Suppress("FunctionName") -public inline fun > A.LabeledPolynomial(block: LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = LabeledPolynomialBuilder(zero, ::add).apply(block).build() -@UnstableKMathAPI -@LabeledPolynomialConstructorDSL -@Suppress("FunctionName") -public inline fun > A.LabeledPolynomial(capacity: Int, block: LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = LabeledPolynomialBuilder(zero, ::add, capacity).apply(block).build() -@UnstableKMathAPI -@LabeledPolynomialConstructorDSL -@Suppress("FunctionName") -public inline fun > LabeledPolynomialSpace.LabeledPolynomial(block: LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = LabeledPolynomialBuilder(constantZero, { left: C, right: C -> left + right}).apply(block).build() -@UnstableKMathAPI -@LabeledPolynomialConstructorDSL -@Suppress("FunctionName") -public inline fun > LabeledPolynomialSpace.LabeledPolynomial(capacity: Int, block: LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = LabeledPolynomialBuilder(constantZero, { left: C, right: C -> left + right}, capacity).apply(block).build() - -// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available - -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): LabeledRationalFunction = - LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients, toCheckInput = true), - LabeledPolynomial(denominatorCoefficients, toCheckInput = true) - ) -@Suppress("FunctionName") -public fun > A.LabeledRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): LabeledRationalFunction = - LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients, toCheckInput = true), - LabeledPolynomial(denominatorCoefficients, toCheckInput = true) - ) -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numerator: LabeledPolynomial): LabeledRationalFunction = - LabeledRationalFunction(numerator, polynomialOne) -@Suppress("FunctionName") -public fun > A.LabeledRationalFunction(numerator: LabeledPolynomial): LabeledRationalFunction = - LabeledRationalFunction(numerator, LabeledPolynomial(mapOf(emptyMap() to one), toCheckInput = false)) -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numeratorCoefficients: Map, C>): LabeledRationalFunction = - LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients, toCheckInput = true), - polynomialOne - ) -@Suppress("FunctionName") -public fun > A.LabeledRationalFunction(numeratorCoefficients: Map, C>): LabeledRationalFunction = - LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients, toCheckInput = true), - LabeledPolynomial(mapOf(emptyMap() to one), toCheckInput = false) - ) - -//context(A) -//public fun > Symbol.asLabeledRationalFunction() : LabeledRationalFunction = LabeledRationalFunction(asLabeledPolynomial()) -//context(LabeledRationalFunctionSpace) -//public fun > Symbol.asLabeledRationalFunction() : LabeledRationalFunction = LabeledRationalFunction(asLabeledPolynomial()) - -//context(A) -//public fun > C.asLabeledRationalFunction() : LabeledRationalFunction = LabeledRationalFunction(asLabeledPolynomial()) -//context(LabeledRationalFunctionSpace) -//public fun > C.asLabeledRationalFunction() : LabeledRationalFunction = LabeledRationalFunction(asLabeledPolynomial()) \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt deleted file mode 100644 index af918b9ae..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt +++ /dev/null @@ -1,495 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.Field -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.invoke -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract - - -// TODO: Docs - -/** - * Creates a [LabeledPolynomialSpace] over a received ring. - */ -public fun > A.labeledPolynomial(): LabeledPolynomialSpace = - LabeledPolynomialSpace(this) - -/** - * Creates a [LabeledPolynomialSpace]'s scope over a received ring. - */ -@OptIn(ExperimentalContracts::class) -public inline fun , R> A.labeledPolynomial(block: LabeledPolynomialSpace.() -> R): R { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return LabeledPolynomialSpace(this).block() -} - -///** -// * Represents the polynomial as a [String] with names of variables substituted with names from [names]. -// * Consider that monomials are sorted in lexicographic order. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.represent(names: Map = emptyMap()): String = -// coefficients.entries -// .sortedWith { o1, o2 -> LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } -// .asSequence() -// .map { (degs, t) -> -// if (degs.isEmpty()) "$t" -// else { -// when { -// t.isOne() -> "" -// t.isMinusOne() -> "-" -// else -> "$t " -// } + -// degs -// .toSortedMap() -// .filter { it.value > 0U } -// .map { (variable, deg) -> -// val variableName = names.getOrDefault(variable, variable.toString()) -// when (deg) { -// 1U -> variableName -// else -> "$variableName^$deg" -// } -// } -// .joinToString(separator = " ") { it } -// } -// } -// .joinToString(separator = " + ") { it } -// .ifEmpty { "0" } -// -///** -// * Represents the polynomial as a [String] naming variables by [namer]. -// * Consider that monomials are sorted in lexicographic order. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.represent(namer: (Symbol) -> String): String = -// coefficients.entries -// .sortedWith { o1, o2 -> LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } -// .asSequence() -// .map { (degs, t) -> -// if (degs.isEmpty()) "$t" -// else { -// when { -// t.isOne() -> "" -// t.isMinusOne() -> "-" -// else -> "$t " -// } + -// degs -// .toSortedMap() -// .filter { it.value > 0U } -// .map { (variable, deg) -> -// when (deg) { -// 1U -> namer(variable) -// else -> "${namer(variable)}^$deg" -// } -// } -// .joinToString(separator = " ") { it } -// } -// } -// .joinToString(separator = " + ") { it } -// .ifEmpty { "0" } -// -///** -// * Represents the polynomial as a [String] with names of variables substituted with names from [names] and with -// * brackets around the string if needed (i.e. when there are at least two addends in the representation). -// * Consider that monomials are sorted in lexicographic order. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.representWithBrackets(names: Map = emptyMap()): String = -// with(represent(names)) { if (coefficients.count() == 1) this else "($this)" } -// -///** -// * Represents the polynomial as a [String] naming variables by [namer] and with brackets around the string if needed -// * (i.e. when there are at least two addends in the representation). -// * Consider that monomials are sorted in lexicographic order. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.representWithBrackets(namer: (Symbol) -> String): String = -// with(represent(namer)) { if (coefficients.count() == 1) this else "($this)" } -// -///** -// * Represents the polynomial as a [String] with names of variables substituted with names from [names]. -// * Consider that monomials are sorted in **reversed** lexicographic order. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.representReversed(names: Map = emptyMap()): String = -// coefficients.entries -// .sortedWith { o1, o2 -> -LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } -// .asSequence() -// .map { (degs, t) -> -// if (degs.isEmpty()) "$t" -// else { -// when { -// t.isOne() -> "" -// t.isMinusOne() -> "-" -// else -> "$t " -// } + -// degs -// .toSortedMap() -// .filter { it.value > 0U } -// .map { (variable, deg) -> -// val variableName = names.getOrDefault(variable, variable.toString()) -// when (deg) { -// 1U -> variableName -// else -> "$variableName^$deg" -// } -// } -// .joinToString(separator = " ") { it } -// } -// } -// .joinToString(separator = " + ") { it } -// .ifEmpty { "0" } -// -///** -// * Represents the polynomial as a [String] naming variables by [namer]. -// * Consider that monomials are sorted in **reversed** lexicographic order. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.representReversed(namer: (Symbol) -> String): String = -// coefficients.entries -// .sortedWith { o1, o2 -> -LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } -// .asSequence() -// .map { (degs, t) -> -// if (degs.isEmpty()) "$t" -// else { -// when { -// t.isOne() -> "" -// t.isMinusOne() -> "-" -// else -> "$t " -// } + -// degs -// .toSortedMap() -// .filter { it.value > 0U } -// .map { (variable, deg) -> -// when (deg) { -// 1U -> namer(variable) -// else -> "${namer(variable)}^$deg" -// } -// } -// .joinToString(separator = " ") { it } -// } -// } -// .joinToString(separator = " + ") { it } -// .ifEmpty { "0" } -// -///** -// * Represents the polynomial as a [String] with names of variables substituted with names from [names] and with -// * brackets around the string if needed (i.e. when there are at least two addends in the representation). -// * Consider that monomials are sorted in **reversed** lexicographic order. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.representReversedWithBrackets(names: Map = emptyMap()): String = -// with(representReversed(names)) { if (coefficients.count() == 1) this else "($this)" } -// -///** -// * Represents the polynomial as a [String] naming variables by [namer] and with brackets around the string if needed -// * (i.e. when there are at least two addends in the representation). -// * Consider that monomials are sorted in **reversed** lexicographic order. -// */ -//context(LabeledPolynomialSpace) -//fun > LabeledPolynomial.representReversedWithBrackets(namer: (Symbol) -> String): String = -// with(representReversed(namer)) { if (coefficients.count() == 1) this else "($this)" } - -//operator fun > Polynomial.div(other: T): Polynomial = -// if (other.isZero()) throw ArithmeticException("/ by zero") -// else -// Polynomial( -// coefficients -// .mapValues { it.value / other }, -// toCheckInput = false -// ) - -//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 = degs.entries.asSequence().filter { it.key in args }.fold(c) { acc, (variable, deg) -> -// multiplyWithPower(acc, args[variable]!!, deg) -// } -// this[newDegs] = if (newDegs in this) this[newDegs]!! + newC else newC -// } -// } -// ) -//} -// -//// TODO: Replace with optimisation: the [result] may be unboxed, and all operations may be performed as soon as -//// possible on it -//@JvmName("substitutePolynomial") -//fun LabeledPolynomial.substitute(ring: Ring, arg: Map>) : LabeledPolynomial = -// ring.labeledPolynomial { -// if (coefficients.isEmpty()) return zero -// coefficients -// .asSequence() -// .map { (degs, c) -> -// degs.entries -// .asSequence() -// .filter { it.key in arg } -// .fold(LabeledPolynomial(mapOf(degs.filterKeys { it !in arg } to c))) { acc, (index, deg) -> -// multiplyWithPower(acc, arg[index]!!, deg) -// } -// } -// .reduce { acc, polynomial -> acc + polynomial } // TODO: Rewrite. Might be slow. -// } -// -//// TODO: Substitute rational function -// -//fun > LabeledPolynomial.asFunctionOver(ring: A): (Map) -> LabeledPolynomial = -// { substitute(ring, it) } -// -//fun > LabeledPolynomial.asPolynomialFunctionOver(ring: A): (Map>) -> LabeledPolynomial = -// { substitute(ring, it) } - -/** - * Returns algebraic derivative of received polynomial. - */ -@UnstableKMathAPI -public fun > LabeledPolynomial.derivativeWithRespectTo( - algebra: A, - variable: Symbol, -): LabeledPolynomial = algebra { - LabeledPolynomial( - buildMap(coefficients.size) { - 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. - */ -@UnstableKMathAPI -public fun > LabeledPolynomial.derivativeWithRespectTo( - algebra: A, - variables: Collection, -): LabeledPolynomial = algebra { - val cleanedVariables = variables.toSet() - if (cleanedVariables.isEmpty()) return this@derivativeWithRespectTo - LabeledPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - if (!degs.keys.containsAll(cleanedVariables)) return@forEach - put( - buildMap { - degs.forEach { (vari, deg) -> - when { - vari !in cleanedVariables -> put(vari, deg) - deg > 1u -> put(vari, deg - 1u) - } - } - }, - cleanedVariables.fold(c) { acc, variable -> multiplyByDoubling(acc, degs[variable]!!) } - ) - } - } - ) -} - -/** - * Returns algebraic derivative of received polynomial. - */ -@UnstableKMathAPI -public fun > LabeledPolynomial.nthDerivativeWithRespectTo( - algebra: A, - variable: Symbol, - order: UInt -): LabeledPolynomial = algebra { - if (order == 0u) return this@nthDerivativeWithRespectTo - LabeledPolynomial( - buildMap(coefficients.size) { - 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. - */ -@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.size) { - 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. - */ -@UnstableKMathAPI -public fun > LabeledPolynomial.antiderivativeWithRespectTo( - algebra: A, - variable: Symbol, -): LabeledPolynomial = algebra { - LabeledPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - val newDegs = buildMap(degs.size + 1) { - put(variable, 1u) - for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) - } - put( - newDegs, - c / multiplyByDoubling(one, newDegs[variable]!!) - ) - } - } - ) -} - -/** - * Returns algebraic antiderivative of received polynomial. - */ -@UnstableKMathAPI -public fun > LabeledPolynomial.antiderivativeWithRespectTo( - algebra: A, - variables: Collection, -): LabeledPolynomial = algebra { - val cleanedVariables = variables.toSet() - if (cleanedVariables.isEmpty()) return this@antiderivativeWithRespectTo - LabeledPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - val newDegs = buildMap(degs.size + 1) { - for (variable in cleanedVariables) put(variable, 1u) - for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) - } - put( - newDegs, - cleanedVariables.fold(c) { acc, variable -> acc / multiplyByDoubling(one, newDegs[variable]!!) } - ) - } - } - ) -} - -/** - * Returns algebraic derivative of received polynomial. - */ -@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 = buildMap(degs.size + 1) { - put(variable, order) - for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) - } - 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. - */ -@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 = buildMap(degs.size + 1) { - for ((variable, order) in filteredVariablesAndOrders) put(variable, order) - for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) - } - 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-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt deleted file mode 100644 index 583160cf4..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledRationalFunctionUtil.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.operations.Ring -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract - - -/** - * Creates a [LabeledRationalFunctionSpace] over a received ring. - */ -public fun > A.labeledRationalFunction(): LabeledRationalFunctionSpace = - LabeledRationalFunctionSpace(this) - -/** - * Creates a [LabeledRationalFunctionSpace]'s scope over a received ring. - */ -public inline fun , R> A.labeledRationalFunction(block: LabeledRationalFunctionSpace.() -> R): R { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return LabeledRationalFunctionSpace(this).block() -} - -//fun > LabeledRationalFunction.reduced(): LabeledRationalFunction { -// val greatestCommonDivider = polynomialGCD(numerator, denominator) -// return LabeledRationalFunction( -// numerator / greatestCommonDivider, -// denominator / greatestCommonDivider -// ) -//} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt index 9498c77ca..35c736914 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt @@ -3,58 +3,95 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + package space.kscience.kmath.functions import space.kscience.kmath.operations.Ring /** - * Returns a [ListPolynomial] instance with given [coefficients]. The collection of coefficients will be reversed if - * [reverse] parameter is true. + * 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 }) /** - * Returns a [ListPolynomial] instance with given [coefficients]. The collection of coefficients will be reversed if - * [reverse] parameter is true. + * 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 } ) ) -@Suppress("FunctionName") -public fun > ListRationalFunctionSpace.ListRationalFunction(numerator: ListPolynomial): ListRationalFunction = - ListRationalFunction(numerator, polynomialOne) +/** + * 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(numeratorCoefficients: List, reverse: Boolean = false): ListRationalFunction = - ListRationalFunction( - ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), - polynomialOne - ) +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-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt deleted file mode 100644 index 50313cab9..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.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.min -import kotlin.math.pow - - -/** - * Removes zeros on the end of the coefficient list of polynomial. - */ -//context(PolynomialSpace) -//fun > Polynomial.removeZeros() : Polynomial = -// if (degree > -1) Polynomial(coefficients.subList(0, degree + 1)) else zero - -/** - * Creates a [ListPolynomialSpace] over a received ring. - */ -public fun > A.listPolynomial(): ListPolynomialSpace = - ListPolynomialSpace(this) - -/** - * Creates a [ListPolynomialSpace]'s scope over a received ring. - */ -public inline fun , R> A.listPolynomial(block: ListPolynomialSpace.() -> R): R { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return ListPolynomialSpace(this).block() -} - -/** - * Creates a [ScalableListPolynomialSpace] over a received scalable ring. - */ -public fun A.scalableListPolynomial(): ScalableListPolynomialSpace where A : Ring, A : ScaleOperations = - ScalableListPolynomialSpace(this) - -/** - * Creates a [ScalableListPolynomialSpace]'s scope over a received scalable ring. - */ -public inline fun A.scalableListPolynomial(block: ScalableListPolynomialSpace.() -> R): R where A : Ring, A : ScaleOperations { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return ScalableListPolynomialSpace(this).block() -} - -@Suppress("NOTHING_TO_INLINE") -internal inline fun copyTo( - origin: List, - originDegree: Int, - target: MutableList, -) { - for (deg in 0 .. originDegree) target[deg] = origin[deg] -} - -@Suppress("NOTHING_TO_INLINE") -internal inline fun multiplyAddingToUpdater( - ring: Ring, - multiplicand: MutableList, - multiplicandDegree: Int, - multiplier: List, - multiplierDegree: Int, - updater: MutableList, - zero: C, -) { - multiplyAddingTo( - ring = ring, - multiplicand = multiplicand, - multiplicandDegree = multiplicandDegree, - multiplier = multiplier, - multiplierDegree = multiplierDegree, - target = updater - ) - for (updateDeg in 0 .. multiplicandDegree + multiplierDegree) { - multiplicand[updateDeg] = updater[updateDeg] - updater[updateDeg] = zero - } -} - -@Suppress("NOTHING_TO_INLINE") -internal inline fun multiplyAddingTo( - ring: Ring, - multiplicand: List, - multiplicandDegree: Int, - multiplier: List, - multiplierDegree: Int, - target: MutableList -) = ring { - for (d in 0 .. multiplicandDegree + multiplierDegree) - for (k in max(0, d - multiplierDegree)..min(multiplicandDegree, d)) - target[d] += multiplicand[k] * multiplier[d - k] -} - -/** - * Evaluates the value of the given double polynomial for given double argument. - */ -public fun ListPolynomial.substitute(arg: Double): Double = - coefficients.reduceIndexedOrNull { index, acc, c -> - acc + c * arg.pow(index) - } ?: .0 - -/** - * Evaluates the value of the given polynomial for given 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@ring zero - var result: C = coefficients.last() - for (j in coefficients.size - 2 downTo 0) { - result = (arg * result) + coefficients[j] - } - return result -} - -public fun ListPolynomial.substitute(ring: Ring, arg: ListPolynomial) : ListPolynomial = ring { - if (coefficients.isEmpty()) return ListPolynomial(emptyList()) - - val thisDegree = coefficients.lastIndex - if (thisDegree == -1) return ListPolynomial(emptyList()) - val argDegree = arg.coefficients.lastIndex - if (argDegree == -1) return coefficients[0].asListPolynomial() - val constantZero = zero - val resultCoefs: MutableList = MutableList(thisDegree * argDegree + 1) { constantZero } - resultCoefs[0] = coefficients[thisDegree] - val resultCoefsUpdate: MutableList = MutableList(thisDegree * argDegree + 1) { constantZero } - var resultDegree = 0 - for (deg in thisDegree - 1 downTo 0) { - resultCoefsUpdate[0] = coefficients[deg] - multiplyAddingToUpdater( - ring = ring, - multiplicand = resultCoefs, - multiplicandDegree = resultDegree, - multiplier = arg.coefficients, - multiplierDegree = argDegree, - updater = resultCoefsUpdate, - zero = constantZero - ) - resultDegree += argDegree - } - - return ListPolynomial(resultCoefs) -} - -/** - * Represent the polynomial as a regular context-less function. - */ -public fun > ListPolynomial.asFunction(ring: A): (C) -> C = { substitute(ring, it) } - -/** - * Represent the polynomial as a regular context-less function. - */ -public fun > ListPolynomial.asPolynomialFunctionOver(ring: A): (ListPolynomial) -> ListPolynomial = { substitute(ring, it) } - -/** - * Returns algebraic derivative of received polynomial. - */ -@UnstableKMathAPI -public fun ListPolynomial.derivative( - algebra: A, -): ListPolynomial where A : Ring, A : NumericAlgebra = algebra { - ListPolynomial( - buildList(max(0, coefficients.size - 1)) { - for (deg in 1 .. coefficients.lastIndex) add(number(deg) * coefficients[deg]) - } - ) -} - -/** - * Returns algebraic derivative of received polynomial. - */ -@UnstableKMathAPI -public fun ListPolynomial.nthDerivative( - algebra: A, - order: Int, -): ListPolynomial where A : Ring, A : NumericAlgebra = algebra { - 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( - algebra: A, -): ListPolynomial where A : Field, A : NumericAlgebra = algebra { - ListPolynomial( - buildList(coefficients.size + 1) { - add(zero) - coefficients.mapIndexedTo(this) { index, t -> t / number(index + 1) } - } - ) -} - -/** - * Returns algebraic antiderivative of received polynomial. - */ -@UnstableKMathAPI -public fun ListPolynomial.nthAntiderivative( - algebra: A, - order: Int, -): ListPolynomial where A : Field, A : NumericAlgebra = algebra { - 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) } } - } - ) -} - -/** - * Compute a definite integral of a given polynomial in a [range] - */ -@UnstableKMathAPI -public fun > ListPolynomial.integrate( - algebra: Field, - range: ClosedRange, -): C = algebra { - val integral = antiderivative(algebra) - integral.substitute(algebra, range.endInclusive) - integral.substitute(algebra, range.start) -} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt new file mode 100644 index 000000000..127dd8c7a --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt @@ -0,0 +1,268 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.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 fun > A.listPolynomialSpace(): ListPolynomialSpace = + 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 fun A.scalableListPolynomialSpace(): ScalableListPolynomialSpace where A : Ring, A : ScaleOperations = + 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 fun > A.listRationalFunctionSpace(): ListRationalFunctionSpace = + 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.asPolynomialFunctionOver(ring: A): (ListPolynomial) -> ListPolynomial = { substitute(ring, it) } + +/** + * Represent [this] polynomial as a regular context-less function. + */ +public fun > ListPolynomial.asFunctionOfRationalFunctionOver(ring: A): (ListPolynomial) -> ListPolynomial = { 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.asPolynomialFunctionOver(ring: A): (ListPolynomial) -> ListRationalFunction = { substitute(ring, it) } + +/** + * Represent [this] rational function as a regular context-less function. + */ +public fun > ListRationalFunction.asFunctionOfRationalFunctionOver(ring: A): (ListPolynomial) -> 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) +} + +/** + * Returns algebraic derivative of received rational function. + */ +@UnstableKMathAPI +public fun ListRationalFunction.derivative( + ring: A, +): ListRationalFunction where A : Ring, A : NumericAlgebra = ring.listRationalFunctionSpace { + ListRationalFunction( + numerator.derivative(ring) * denominator - numerator * denominator.derivative(ring), + denominator * denominator + ) +} + +/** + * Returns algebraic derivative of received rational function of specified [order]. The [order] should be non-negative integer. + */ +@UnstableKMathAPI +public tailrec fun ListRationalFunction.nthDerivative( + ring: A, + order: Int, +): ListRationalFunction where A : Ring, A : NumericAlgebra = + if (order == 0) this else derivative(ring).nthDerivative(ring, order - 1) \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listRationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtilOptimized.kt similarity index 72% rename from kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listRationalFunctionUtil.kt rename to kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtilOptimized.kt index 367212588..6eb3a1dc7 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listRationalFunctionUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtilOptimized.kt @@ -5,41 +5,91 @@ package space.kscience.kmath.functions -import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.invoke -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract import kotlin.math.max +import kotlin.math.min -/** - * Creates a [ListRationalFunctionSpace] over a received ring. - */ -public fun > A.listRationalFunction(): ListRationalFunctionSpace = - ListRationalFunctionSpace(this) - -/** - * Creates a [ListRationalFunctionSpace]'s scope over a received ring. - */ -public inline fun , R> A.listRationalFunction(block: ListRationalFunctionSpace.() -> R): R { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return ListRationalFunctionSpace(this).block() +// TODO: Optimized copies of substitution and invocation +@UnstablePolynomialBoxingOptimization +@Suppress("NOTHING_TO_INLINE") +internal inline fun copyTo( + origin: List, + originDegree: Int, + target: MutableList, +) { + for (deg in 0 .. originDegree) target[deg] = origin[deg] } -/** - * Evaluates the value of the given double polynomial for given double argument. - */ -public fun ListRationalFunction.substitute(arg: Double): Double = - numerator.substitute(arg) / denominator.substitute(arg) +@UnstablePolynomialBoxingOptimization +@Suppress("NOTHING_TO_INLINE") +internal inline fun multiplyAddingToUpdater( + ring: Ring, + multiplicand: MutableList, + multiplicandDegree: Int, + multiplier: List, + multiplierDegree: Int, + updater: MutableList, + zero: C, +) { + multiplyAddingTo( + ring = ring, + multiplicand = multiplicand, + multiplicandDegree = multiplicandDegree, + multiplier = multiplier, + multiplierDegree = multiplierDegree, + target = updater + ) + for (updateDeg in 0 .. multiplicandDegree + multiplierDegree) { + multiplicand[updateDeg] = updater[updateDeg] + updater[updateDeg] = zero + } +} -/** - * Evaluates the value of the given polynomial for given 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) +@UnstablePolynomialBoxingOptimization +@Suppress("NOTHING_TO_INLINE") +internal inline fun multiplyAddingTo( + ring: Ring, + multiplicand: List, + multiplicandDegree: Int, + multiplier: List, + multiplierDegree: Int, + target: MutableList +) = ring { + for (d in 0 .. multiplicandDegree + multiplierDegree) + for (k in max(0, d - multiplierDegree)..min(multiplicandDegree, d)) + target[d] += multiplicand[k] * multiplier[d - k] +} + +@UnstablePolynomialBoxingOptimization +public fun ListPolynomial.substitute2(ring: Ring, arg: ListPolynomial) : ListPolynomial = ring { + if (coefficients.isEmpty()) return ListPolynomial(emptyList()) + + val thisDegree = coefficients.lastIndex + if (thisDegree == -1) return ListPolynomial(emptyList()) + val argDegree = arg.coefficients.lastIndex + if (argDegree == -1) return coefficients[0].asListPolynomial() + val constantZero = zero + val resultCoefs: MutableList = MutableList(thisDegree * argDegree + 1) { constantZero } + resultCoefs[0] = coefficients[thisDegree] + val resultCoefsUpdate: MutableList = MutableList(thisDegree * argDegree + 1) { constantZero } + var resultDegree = 0 + for (deg in thisDegree - 1 downTo 0) { + resultCoefsUpdate[0] = coefficients[deg] + multiplyAddingToUpdater( + ring = ring, + multiplicand = resultCoefs, + multiplicandDegree = resultDegree, + multiplier = arg.coefficients, + multiplierDegree = argDegree, + updater = resultCoefsUpdate, + zero = constantZero + ) + resultDegree += argDegree + } + + return ListPolynomial(resultCoefs) } /** @@ -52,6 +102,7 @@ public fun ListRationalFunction.substitute(ring: Field, arg: C): C = r * * Used in [ListPolynomial.substitute] and [ListRationalFunction.substitute] for performance optimisation. */ // TODO: Дописать +@UnstablePolynomialBoxingOptimization internal fun ListPolynomial.substituteRationalFunctionTakeNumerator(ring: Ring, arg: ListRationalFunction): ListPolynomial = ring { if (coefficients.isEmpty()) return ListPolynomial(emptyList()) @@ -196,26 +247,4 @@ internal fun ListPolynomial.substituteRationalFunctionTakeNumerator(ring: end = thisDegree + 1 ) ) -} - -//operator fun > RationalFunction.invoke(arg: T): T = numerator(arg) / denominator(arg) -// -//fun > RationalFunction.reduced(): RationalFunction = -// polynomialGCD(numerator, denominator).let { -// RationalFunction( -// numerator / it, -// denominator / it -// ) -// } - -///** -// * Returns result of applying formal derivative to the polynomial. -// * -// * @param T Field where we are working now. -// * @return Result of the operator. -// */ -//fun > RationalFunction.derivative() = -// RationalFunction( -// numerator.derivative() * denominator - denominator.derivative() * numerator, -// denominator * denominator -// ) \ No newline at end of file +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt new file mode 100644 index 000000000..8b6fac39e --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + + +@RequiresOptIn( + message = "It's copy of operation with optimized boxing. It's currently unstable.", + level = RequiresOptIn.Level.ERROR +) +internal annotation class UnstablePolynomialBoxingOptimization \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt deleted file mode 100644 index dca8a0cff..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.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) - -// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(coefs, toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(coefs, toCheckInput) -@Suppress("FunctionName") -internal fun > A.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial { - if (!toCheckInput) return NumberedPolynomial(coefs) - - val fixedCoefs = mutableMapOf, C>() - - for (entry in coefs) { - val key = entry.key.cleanUp() - val value = entry.value - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return NumberedPolynomial(fixedCoefs) -} - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs, toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs, toCheckInput) -@Suppress("FunctionName") -internal fun > A.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial { - if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) - - val fixedCoefs = mutableMapOf, C>() - - for (entry in pairs) { - val key = entry.first.cleanUp() - val value = entry.second - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return NumberedPolynomial(fixedCoefs) -} - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs = pairs, toCheckInput = toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs = pairs, toCheckInput = toCheckInput) -@Suppress("FunctionName") -internal fun > A.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial { - if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) - - val fixedCoefs = mutableMapOf, C>() - - for (entry in pairs) { - val key = entry.first.cleanUp() - val value = entry.second - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return NumberedPolynomial(fixedCoefs) -} - -@Suppress("FunctionName") -public fun > A.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedPolynomialSpace.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) - -@Suppress("FunctionName") -public fun > A.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedPolynomialSpace.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) - -@Suppress("FunctionName") -public fun > A.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedPolynomialSpace.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) - -public fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(emptyList() to this)) - -@DslMarker -@UnstableKMathAPI -internal annotation class NumberedPolynomialConstructorDSL - -@UnstableKMathAPI -@NumberedPolynomialConstructorDSL -public class NumberedPolynomialTermSignatureBuilder { - private val signature: MutableList = ArrayList() - public fun build(): List = signature - public infix fun Int.inPowerOf(deg: UInt) { - if (this > signature.lastIndex) { - signature.addAll(List(this - signature.lastIndex - 1) { 0u }) - signature.add(deg) - } else { - signature[this] = deg - } - } - @Suppress("NOTHING_TO_INLINE") - public inline infix fun Int.pow(deg: UInt): Unit = this inPowerOf deg - @Suppress("NOTHING_TO_INLINE") - public inline infix fun Int.`in`(deg: UInt): Unit = this inPowerOf deg - @Suppress("NOTHING_TO_INLINE") - public inline infix fun Int.of(deg: UInt): Unit = this inPowerOf deg -} - -@UnstableKMathAPI -public class NumberedPolynomialBuilder(private val zero: C, private val add: (C, C) -> C, capacity: Int = 0) { - private val coefficients: MutableMap, C> = LinkedHashMap(capacity) - public fun build(): NumberedPolynomial = NumberedPolynomial(coefficients) - public operator fun C.invoke(block: NumberedPolynomialTermSignatureBuilder.() -> Unit) { - val signature = NumberedPolynomialTermSignatureBuilder().apply(block).build() - coefficients[signature] = add(coefficients.getOrElse(signature) { zero }, this@invoke) - } - @Suppress("NOTHING_TO_INLINE") - public inline infix fun C.with(noinline block: NumberedPolynomialTermSignatureBuilder.() -> Unit): Unit = this.invoke(block) - @Suppress("NOTHING_TO_INLINE") - public inline infix fun (NumberedPolynomialTermSignatureBuilder.() -> Unit).with(coef: C): Unit = coef.invoke(this) - @Suppress("NOTHING_TO_INLINE") - public infix fun sig(block: NumberedPolynomialTermSignatureBuilder.() -> Unit): NumberedPolynomialTermSignatureBuilder.() -> Unit = block -} - -// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available - -@UnstableKMathAPI -@NumberedPolynomialConstructorDSL -@Suppress("FunctionName") -public inline fun > A.NumberedPolynomial(block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder(zero, ::add).apply(block).build() -@UnstableKMathAPI -@NumberedPolynomialConstructorDSL -@Suppress("FunctionName") -public inline fun > A.NumberedPolynomial(capacity: Int, block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder(zero, ::add, capacity).apply(block).build() -@UnstableKMathAPI -@NumberedPolynomialConstructorDSL -@Suppress("FunctionName") -public inline fun > NumberedPolynomialSpace.NumberedPolynomial(block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder(constantZero, { left: C, right: C -> left + right}).apply(block).build() -@UnstableKMathAPI -@NumberedPolynomialConstructorDSL -@Suppress("FunctionName") -public inline fun > NumberedPolynomialSpace.NumberedPolynomial(capacity: Int, block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder(constantZero, { left: C, right: C -> left + right}, capacity).apply(block).build() - -// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available - -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): NumberedRationalFunction = - NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients, toCheckInput = true), - NumberedPolynomial(denominatorCoefficients, toCheckInput = true) - ) -@Suppress("FunctionName") -public fun > A.NumberedRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): NumberedRationalFunction = - NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients, toCheckInput = true), - NumberedPolynomial(denominatorCoefficients, toCheckInput = true) - ) -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numerator: NumberedPolynomial): NumberedRationalFunction = - NumberedRationalFunction(numerator, polynomialOne) -@Suppress("FunctionName") -public fun > A.NumberedRationalFunction(numerator: NumberedPolynomial): NumberedRationalFunction = - NumberedRationalFunction(numerator, NumberedPolynomial(mapOf(emptyList() to one), toCheckInput = false)) -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numeratorCoefficients: Map, C>): NumberedRationalFunction = - NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients, toCheckInput = true), - polynomialOne - ) -@Suppress("FunctionName") -public fun > A.NumberedRationalFunction(numeratorCoefficients: Map, C>): NumberedRationalFunction = - NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients, toCheckInput = true), - NumberedPolynomial(mapOf(emptyList() to one), toCheckInput = false) - ) - -//context(A) -//public fun > C.asNumberedRationalFunction() : NumberedRationalFunction = NumberedRationalFunction(asLabeledPolynomial()) -//context(NumberedRationalFunctionSpace) -//public fun > C.asNumberedRationalFunction() : NumberedRationalFunction = NumberedRationalFunction(asLabeledPolynomial()) \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt deleted file mode 100644 index ad817c7ba..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt +++ /dev/null @@ -1,528 +0,0 @@ -package space.kscience.kmath.functions - -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.* -import kotlin.contracts.* -import kotlin.jvm.JvmName -import kotlin.math.max - - -// TODO: Docs - -/** - * Creates a [NumberedPolynomialSpace] over a received ring. - */ -public fun > A.numberedPolynomial(): NumberedPolynomialSpace = - NumberedPolynomialSpace(this) - -/** - * Creates a [NumberedPolynomialSpace]'s scope over a received ring. - */ -@OptIn(ExperimentalContracts::class) -public inline fun , R> A.numberedPolynomial(block: NumberedPolynomialSpace.() -> R): R { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return NumberedPolynomialSpace(this).block() -} - -///** -// * Represents the polynomial as a [String] where name of variable with index `i` is [withVariableName] + `"_${i+1}"`. -// * Consider that monomials are sorted in lexicographic order. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial.represent(withVariableName: String = NumberedPolynomial.defaultVariableName): String = -// coefficients.entries -// .sortedWith { o1, o2 -> NumberedPolynomial.monomialComparator.compare(o1.key, o2.key) } -// .asSequence() -// .map { (degs, t) -> -// if (degs.isEmpty()) "$t" -// else { -// when { -// t.isOne() -> "" -// t.isMinusOne() -> "-" -// else -> "$t " -// } + -// degs -// .mapIndexed { index, deg -> -// when (deg) { -// 0U -> "" -// 1U -> "${withVariableName}_${index+1}" -// else -> "${withVariableName}_${index+1}^$deg" -// } -// } -// .filter { it.isNotEmpty() } -// .joinToString(separator = " ") { it } -// } -// } -// .joinToString(separator = " + ") { it } -// .ifEmpty { "0" } -// -///** -// * Represents the polynomial as a [String] naming variables by [namer]. -// * Consider that monomials are sorted in lexicographic order. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial.represent(namer: (Int) -> String): String = -// coefficients.entries -// .sortedWith { o1, o2 -> NumberedPolynomial.monomialComparator.compare(o1.key, o2.key) } -// .asSequence() -// .map { (degs, t) -> -// if (degs.isEmpty()) "$t" -// else { -// when { -// t.isOne() -> "" -// t.isMinusOne() -> "-" -// else -> "$t " -// } + -// degs -// .mapIndexed { index, deg -> -// when (deg) { -// 0U -> "" -// 1U -> namer(index) -// else -> "${namer(index)}^$deg" -// } -// } -// .filter { it.isNotEmpty() } -// .joinToString(separator = " ") { it } -// } -// } -// .joinToString(separator = " + ") { it } -// .ifEmpty { "0" } -// -///** -// * Represents the polynomial as a [String] where name of variable with index `i` is [withVariableName] + `"_${i+1}"` -// * and with brackets around the string if needed (i.e. when there are at least two addends in the representation). -// * Consider that monomials are sorted in lexicographic order. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial.representWithBrackets(withVariableName: String = NumberedPolynomial.defaultVariableName): String = -// with(represent(withVariableName)) { if (coefficients.count() == 1) this else "($this)" } -// -///** -// * Represents the polynomial as a [String] naming variables by [namer] and with brackets around the string if needed -// * (i.e. when there are at least two addends in the representation). -// * Consider that monomials are sorted in lexicographic order. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial.representWithBrackets(namer: (Int) -> String): String = -// with(represent(namer)) { if (coefficients.count() == 1) this else "($this)" } -// -///** -// * Represents the polynomial as a [String] where name of variable with index `i` is [withVariableName] + `"_${i+1}"`. -// * Consider that monomials are sorted in **reversed** lexicographic order. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial.representReversed(withVariableName: String = NumberedPolynomial.defaultVariableName): String = -// coefficients.entries -// .sortedWith { o1, o2 -> -NumberedPolynomial.monomialComparator.compare(o1.key, o2.key) } -// .asSequence() -// .map { (degs, t) -> -// if (degs.isEmpty()) "$t" -// else { -// when { -// t.isOne() -> "" -// t.isMinusOne() -> "-" -// else -> "$t " -// } + -// degs -// .mapIndexed { index, deg -> -// when (deg) { -// 0U -> "" -// 1U -> "${withVariableName}_${index+1}" -// else -> "${withVariableName}_${index+1}^$deg" -// } -// } -// .filter { it.isNotEmpty() } -// .joinToString(separator = " ") { it } -// } -// } -// .joinToString(separator = " + ") { it } -// .ifEmpty { "0" } -// -///** -// * Represents the polynomial as a [String] naming variables by [namer]. -// * Consider that monomials are sorted in **reversed** lexicographic order. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial.representReversed(namer: (Int) -> String): String = -// coefficients.entries -// .sortedWith { o1, o2 -> -NumberedPolynomial.monomialComparator.compare(o1.key, o2.key) } -// .asSequence() -// .map { (degs, t) -> -// if (degs.isEmpty()) "$t" -// else { -// when { -// t.isOne() -> "" -// t.isMinusOne() -> "-" -// else -> "$t " -// } + -// degs -// .mapIndexed { index, deg -> -// when (deg) { -// 0U -> "" -// 1U -> namer(index) -// else -> "${namer(index)}^$deg" -// } -// } -// .filter { it.isNotEmpty() } -// .joinToString(separator = " ") { it } -// } -// } -// .joinToString(separator = " + ") { it } -// .ifEmpty { "0" } -// -///** -// * Represents the polynomial as a [String] where name of variable with index `i` is [withVariableName] + `"_${i+1}"` -// * and with brackets around the string if needed (i.e. when there are at least two addends in the representation). -// * Consider that monomials are sorted in **reversed** lexicographic order. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial.representReversedWithBrackets(withVariableName: String = NumberedPolynomial.defaultVariableName): String = -// with(representReversed(withVariableName)) { if (coefficients.count() == 1) this else "($this)" } -// -///** -// * Represents the polynomial as a [String] naming variables by [namer] and with brackets around the string if needed -// * (i.e. when there are at least two addends in the representation). -// * Consider that monomials are sorted in **reversed** lexicographic order. -// */ -//context(NumberedPolynomialSpace) -//public fun > NumberedPolynomial.representReversedWithBrackets(namer: (Int) -> String): String = -// with(representReversed(namer)) { if (coefficients.count() == 1) this else "($this)" } - -//public fun NumberedPolynomial.substitute(ring: Ring, args: Map): NumberedPolynomial = ring { -// if (coefficients.isEmpty()) return this@substitute -// NumberedPolynomial( -// buildMap { -// coefficients.forEach { (degs, c) -> -// val newDegs = degs.mapIndexed { index, deg -> if (index in args) 0U else deg }.cleanUp() -// val newC = degs.foldIndexed(c) { index, acc, deg -> -// if (index in args) multiplyWithPower(acc, args[index]!!, deg) -// else acc -// } -// this[newDegs] = if (newDegs in this) this[newDegs]!! + newC else newC -// } -// } -// ) -//} -// -//// TODO: Replace with optimisation: the [result] may be unboxed, and all operations may be performed as soon as -//// possible on it -//@JvmName("substitutePolynomial") -//public fun NumberedPolynomial.substitute(ring: Ring, arg: Map>) : NumberedPolynomial = -// ring.numberedPolynomialSpace { -// if (coefficients.isEmpty()) return zero -// coefficients -// .asSequence() -// .map { (degs, c) -> -// degs.foldIndexed( -// NumberedPolynomial( -// degs.mapIndexed { index, deg -> if (index in arg) 0U else deg } to c -// ) -// ) { index, acc, deg -> if (index in arg) multiplyWithPower(acc, arg[index]!!, deg) else acc } -// } -// .reduce { acc, polynomial -> acc + polynomial } // TODO: Rewrite. Might be slow. -// } -// -//// TODO: Substitute rational function -// -//public fun > NumberedPolynomial.asFunctionOver(ring: A): (Map) -> NumberedPolynomial = -// { substitute(ring, it) } -// -//public fun > NumberedPolynomial.asPolynomialFunctionOver(ring: A): (Map>) -> NumberedPolynomial = -// { substitute(ring, it) } - -//operator fun > Polynomial.div(other: T): Polynomial = -// if (other.isZero()) throw ArithmeticException("/ by zero") -// else -// Polynomial( -// coefficients -// .mapValues { it.value / other }, -// toCheckInput = false -// ) - -/** - * Evaluates the value of the given double polynomial for given double argument. - */ -public fun NumberedPolynomial.substitute(args: Map): NumberedPolynomial = Double.algebra { - val acc = LinkedHashMap, Double>(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()) - } - if (newDegs !in acc) acc[newDegs] = newC - else acc[newDegs] = acc[newDegs]!! + newC - } - return NumberedPolynomial(acc) -} - -/** - * Evaluates the value of the given polynomial for given argument. - * - * It is an implementation of [Horner's method](https://en.wikipedia.org/wiki/Horner%27s_method). - */ -public fun NumberedPolynomial.substitute(ring: Ring, args: Map): NumberedPolynomial = ring { - val acc = LinkedHashMap, C>(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) - } - if (newDegs !in acc) acc[newDegs] = newC - else acc[newDegs] = acc[newDegs]!! + newC - } - return NumberedPolynomial(acc) -} - -// TODO: (Waiting for hero) Replace with optimisation: the [result] may be unboxed, and all operations may be performed -// as soon as possible on it -@JvmName("substitutePolynomial") -public fun NumberedPolynomial.substitute(ring: Ring, args: Map>) : NumberedPolynomial = TODO() /*ring.numberedPolynomial { - val acc = LinkedHashMap, NumberedPolynomial>(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.asNumberedPolynomial()) { product, (variable, substitution) -> - val deg = degs.getOrElse(variable) { 0u } - if (deg == 0u) product else product * power(substitution, deg) - } - if (newDegs !in acc) acc[newDegs] = c.asNumberedPolynomial() - else acc[newDegs] = acc[newDegs]!! + c - } -}*/ - -/** - * Represent the polynomial as a regular context-less function. - */ -public fun > NumberedPolynomial.asFunction(ring: A): (Map) -> NumberedPolynomial = { substitute(ring, it) } - -/** - * Represent the polynomial as a regular context-less function. - */ -public fun > NumberedPolynomial.asPolynomialFunctionOver(ring: A): (Map>) -> NumberedPolynomial = { substitute(ring, it) } - -/** - * Returns algebraic derivative of received polynomial. - */ -@UnstableKMathAPI -public fun > NumberedPolynomial.derivativeWithRespectTo( - algebra: A, - variable: Int, -): NumberedPolynomial = algebra { - NumberedPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - if (degs.size > 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. - */ -@UnstableKMathAPI -public fun > NumberedPolynomial.derivativeWithRespectTo( - algebra: A, - variables: Collection, -): NumberedPolynomial = algebra { - val cleanedVariables = variables.toSet() - if (cleanedVariables.isEmpty()) return this@derivativeWithRespectTo - val maxRespectedVariable = cleanedVariables.maxOrNull()!! - NumberedPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - if (degs.size > maxRespectedVariable) return@forEach - put( - degs.mapIndexed { index, deg -> - when { - index !in cleanedVariables -> deg - deg > 0u -> deg - 1u - else -> return@forEach - } - }.cleanUp(), - cleanedVariables.fold(c) { acc, variable -> multiplyByDoubling(acc, degs[variable]) } - ) - } - } - ) -} - -/** - * Returns algebraic derivative of received polynomial. - */ -@UnstableKMathAPI -public fun > NumberedPolynomial.nthDerivativeWithRespectTo( - algebra: A, - variable: Int, - order: UInt -): NumberedPolynomial = algebra { - if (order == 0u) return this@nthDerivativeWithRespectTo - NumberedPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - if (degs.size > 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. - */ -@UnstableKMathAPI -public fun > NumberedPolynomial.nthDerivativeWithRespectTo( - algebra: A, - variablesAndOrders: Map, -): NumberedPolynomial = algebra { - 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.size > 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. - */ -@UnstableKMathAPI -public fun > NumberedPolynomial.antiderivativeWithRespectTo( - algebra: A, - variable: Int, -): NumberedPolynomial = algebra { - NumberedPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - put( - List(max(variable + 1, degs.size)) { if (it != variable) degs[it] else degs[it] + 1u }, - c / multiplyByDoubling(one, degs[variable]) - ) - } - } - ) -} - -/** - * Returns algebraic antiderivative of received polynomial. - */ -@UnstableKMathAPI -public fun > NumberedPolynomial.antiderivativeWithRespectTo( - algebra: A, - variables: Collection, -): NumberedPolynomial = algebra { - val cleanedVariables = variables.toSet() - if (cleanedVariables.isEmpty()) return this@antiderivativeWithRespectTo - val maxRespectedVariable = cleanedVariables.maxOrNull()!! - NumberedPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - put( - List(max(maxRespectedVariable + 1, degs.size)) { if (it !in variables) degs[it] else degs[it] + 1u }, - cleanedVariables.fold(c) { acc, variable -> acc / multiplyByDoubling(one, degs[variable]) } - ) - } - } - ) -} - -/** - * Returns algebraic derivative of received polynomial. - */ -@UnstableKMathAPI -public fun > NumberedPolynomial.nthAntiderivativeWithRespectTo( - algebra: A, - variable: Int, - order: UInt -): NumberedPolynomial = algebra { - if (order == 0u) return this@nthAntiderivativeWithRespectTo - NumberedPolynomial( - buildMap(coefficients.size) { - coefficients - .forEach { (degs, c) -> - put( - List(max(variable + 1, degs.size)) { if (it != variable) degs[it] else degs[it] + order }, - degs[variable].let { deg -> - (deg downTo deg - order + 1u) - .fold(c) { acc, ord -> acc / multiplyByDoubling(one, ord) } - } - ) - } - } - ) -} - -/** - * Returns algebraic derivative of received polynomial. - */ -@UnstableKMathAPI -public fun > NumberedPolynomial.nthAntiderivativeWithRespectTo( - algebra: A, - variablesAndOrders: Map, -): NumberedPolynomial = algebra { - 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[it] + filteredVariablesAndOrders.getOrElse(it) { 0u } }, - filteredVariablesAndOrders.entries.fold(c) { acc1, (index, order) -> - degs[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-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt deleted file mode 100644 index 5cd0679ab..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedRationalFunctionUtil.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.operations.Ring -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract - - -/** - * Creates a [NumberedRationalFunctionSpace] over a received ring. - */ -public fun > A.numberedRationalFunction(): NumberedRationalFunctionSpace = - NumberedRationalFunctionSpace(this) - -/** - * Creates a [NumberedRationalFunctionSpace]'s scope over a received ring. - */ -public inline fun , R> A.numberedRationalFunction(block: NumberedRationalFunctionSpace.() -> R): R { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return NumberedRationalFunctionSpace(this).block() -} - -//fun > NumberedRationalFunction.reduced(): NumberedRationalFunction { -// val greatestCommonDivider = polynomialGCD(numerator, denominator) -// return NumberedRationalFunction( -// numerator / greatestCommonDivider, -// denominator / greatestCommonDivider -// ) -//} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt index 5401be707..c9950fac5 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt @@ -12,7 +12,7 @@ import kotlin.test.* class ListPolynomialTest { @Test fun test_Polynomial_Int_plus() { - RationalField.listPolynomial { + RationalField.listPolynomialSpace { assertEquals( ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)), ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + -3, @@ -52,7 +52,7 @@ class ListPolynomialTest { } @Test fun test_Polynomial_Int_minus() { - RationalField.listPolynomial { + RationalField.listPolynomialSpace { assertEquals( ListPolynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - -3, @@ -92,7 +92,7 @@ class ListPolynomialTest { } @Test fun test_Polynomial_Int_times() { - IntModuloRing(35).listPolynomial { + IntModuloRing(35).listPolynomialSpace { assertEquals( ListPolynomial(34, 2, 1, 20, 2), ListPolynomial(22, 26, 13, 15, 26) * 27, @@ -107,7 +107,7 @@ class ListPolynomialTest { } @Test fun test_Int_Polynomial_plus() { - RationalField.listPolynomial { + RationalField.listPolynomialSpace { assertEquals( ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)), -3 + ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)), @@ -147,7 +147,7 @@ class ListPolynomialTest { } @Test fun test_Int_Polynomial_minus() { - RationalField.listPolynomial { + RationalField.listPolynomialSpace { assertEquals( ListPolynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), 3 - ListPolynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7)), @@ -187,7 +187,7 @@ class ListPolynomialTest { } @Test fun test_Int_Polynomial_times() { - IntModuloRing(35).listPolynomial { + IntModuloRing(35).listPolynomialSpace { assertEquals( ListPolynomial(34, 2, 1, 20, 2), 27 * ListPolynomial(22, 26, 13, 15, 26), @@ -202,7 +202,7 @@ class ListPolynomialTest { } @Test fun test_Polynomial_Constant_plus() { - RationalField.listPolynomial { + 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), @@ -242,7 +242,7 @@ class ListPolynomialTest { } @Test fun test_Polynomial_Constant_minus() { - RationalField.listPolynomial { + 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), @@ -282,7 +282,7 @@ class ListPolynomialTest { } @Test fun test_Polynomial_Constant_times() { - IntModuloRing(35).listPolynomial { + IntModuloRing(35).listPolynomialSpace { assertEquals( ListPolynomial(34, 2, 1, 20, 2), ListPolynomial(22, 26, 13, 15, 26) * 27.asConstant(), @@ -297,7 +297,7 @@ class ListPolynomialTest { } @Test fun test_Constant_Polynomial_plus() { - RationalField.listPolynomial { + 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)), @@ -337,7 +337,7 @@ class ListPolynomialTest { } @Test fun test_Constant_Polynomial_minus() { - RationalField.listPolynomial { + 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)), @@ -377,7 +377,7 @@ class ListPolynomialTest { } @Test fun test_Constant_Polynomial_times() { - IntModuloRing(35).listPolynomial { + IntModuloRing(35).listPolynomialSpace { assertEquals( ListPolynomial(34, 2, 1, 20, 2), 27 * ListPolynomial(22, 26, 13, 15, 26), @@ -392,7 +392,7 @@ class ListPolynomialTest { } @Test fun test_Polynomial_unaryMinus() { - RationalField.listPolynomial { + RationalField.listPolynomialSpace { assertEquals( ListPolynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7)), -ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)), @@ -407,7 +407,7 @@ class ListPolynomialTest { } @Test fun test_Polynomial_Polynomial_plus() { - RationalField.listPolynomial { + 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)), @@ -440,7 +440,7 @@ class ListPolynomialTest { } @Test fun test_Polynomial_Polynomial_minus() { - RationalField.listPolynomial { + 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)), @@ -473,7 +473,7 @@ class ListPolynomialTest { } @Test fun test_Polynomial_Polynomial_times() { - IntModuloRing(35).listPolynomial { + IntModuloRing(35).listPolynomialSpace { // (1 + x + x^2) * (1 - x + x^2) ?= 1 + x^2 + x^4 assertEquals( ListPolynomial(1, 0, 1, 0, 1), diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt index c5eb8fb81..69c1611f3 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.functions +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.test.misc.Rational import space.kscience.kmath.test.misc.RationalField import kotlin.test.Test @@ -12,6 +13,7 @@ import kotlin.test.assertEquals import kotlin.test.assertFailsWith +@OptIn(UnstableKMathAPI::class) class ListPolynomialUtilTest { @Test fun test_substitute_Double() { diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt new file mode 100644 index 000000000..89764db46 --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt @@ -0,0 +1,138 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.test.misc + +import space.kscience.kmath.functions.ListPolynomial +import space.kscience.kmath.functions.ListPolynomialSpace +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(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", "NOTHING_TO_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(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 +} + +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) }) \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt new file mode 100644 index 000000000..72bb5942c --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt @@ -0,0 +1,135 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.test.misc + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.Field +import space.kscience.kmath.operations.NumbersAddOps + +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 = + Rational( + numerator * other.denominator + denominator * other.numerator, + denominator * other.denominator + ) + operator fun plus(other: Int): Rational = + Rational( + numerator + denominator * other.toLong(), + denominator + ) + operator fun plus(other: Long): Rational = + Rational( + numerator + denominator * other, + denominator + ) + operator fun minus(other: Rational): Rational = + Rational( + numerator * other.denominator - denominator * other.numerator, + denominator * other.denominator + ) + operator fun minus(other: Int): Rational = + Rational( + numerator - denominator * other.toLong(), + denominator + ) + operator fun minus(other: Long): Rational = + Rational( + numerator - denominator * other, + denominator + ) + operator fun times(other: Rational): Rational = + Rational( + numerator * other.numerator, + denominator * other.denominator + ) + operator fun times(other: Int): Rational = + Rational( + numerator * other.toLong(), + denominator + ) + operator fun times(other: Long): Rational = + Rational( + numerator * other, + denominator + ) + operator fun div(other: Rational): Rational = + Rational( + numerator * other.denominator, + denominator * other.numerator + ) + operator fun div(other: Int): Rational = + Rational( + numerator, + denominator * other.toLong() + ) + operator fun div(other: Long): Rational = + Rational( + numerator, + denominator * other + ) + 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", "NOTHING_TO_INLINE") +@OptIn(UnstableKMathAPI::class) +object RationalField : Field, NumbersAddOps { + override inline val zero: Rational get() = Rational.ZERO + override inline val one: Rational get() = Rational.ONE + + override inline fun number(value: Number): Rational = Rational(value.toLong()) + + override inline fun add(left: Rational, right: Rational): Rational = left + right + override inline fun multiply(left: Rational, right: Rational): Rational = left * right + override inline fun divide(left: Rational, right: Rational): Rational = left / right + override inline fun scale(a: Rational, value: Double): Rational = a * number(value) + + override inline fun Rational.unaryMinus(): Rational = -this + override inline fun Rational.plus(arg: Rational): Rational = this + arg + override inline fun Rational.minus(arg: Rational): Rational = this - arg + override inline fun Rational.times(arg: Rational): Rational = this * arg + override inline fun Rational.div(arg: Rational): Rational = this / arg +} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt new file mode 100644 index 000000000..ed41b9245 --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.test.misc + +import kotlin.math.abs + + +data class BezoutIdentityWithGCD(val first: T, val second: T, val gcd: T) + +tailrec fun gcd(a: Long, b: Long): Long = if (a == 0L) abs(b) else gcd(b % a, a) + +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 -- 2.34.1 From 1fd8dfd7b826718df16017dc7e2960ac85dbc98d Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 13 Jun 2022 11:17:41 +0300 Subject: [PATCH 089/275] refactor Quaternions --- .../kmath/estree/internal/ESTreeBuilder.kt | 7 +- .../kscience/kmath/asm/internal/AsmBuilder.kt | 2 + kmath-complex/build.gradle.kts | 10 +- .../kscience/kmath/complex/Quaternion.kt | 133 ++++++++---------- kmath-geometry/build.gradle.kts | 2 +- .../kmath/geometry/Euclidean2DSpace.kt | 3 - .../kmath/geometry/Euclidean3DSpace.kt | 2 - 7 files changed, 68 insertions(+), 91 deletions(-) diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt index 10a6c4a16..40c446da0 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt @@ -14,11 +14,12 @@ internal class ESTreeBuilder(val bodyCallback: ESTreeBuilder.() -> BaseExp private class GeneratedExpression(val executable: dynamic, val constants: Array) : Expression { @Suppress("UNUSED_VARIABLE") override fun invoke(arguments: Map): T { - val e = executable - val c = constants + //val e = executable + //val c = constants val a = js("{}") arguments.forEach { (key, value) -> a[key.identity] = value } - return js("e(c, a)").unsafeCast() + return executable.call(constants, a).unsafeCast() + //return js("e(c, a)").unsafeCast() } } diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt index a85079fc8..a76b47ecc 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt @@ -49,5 +49,7 @@ internal abstract class AsmBuilder { * ASM Type for [space.kscience.kmath.expressions.Symbol]. */ val SYMBOL_TYPE: Type = getObjectType("space/kscience/kmath/expressions/Symbol") + + const val ARGUMENTS_NAME = "args" } } diff --git a/kmath-complex/build.gradle.kts b/kmath-complex/build.gradle.kts index ea74df646..f0ce631a5 100644 --- a/kmath-complex/build.gradle.kts +++ b/kmath-complex/build.gradle.kts @@ -19,13 +19,15 @@ readme { feature( id = "complex", - description = "Complex Numbers", ref = "src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt" - ) + ){ + "Complex numbers operations" + } feature( id = "quaternion", - description = "Quaternions", ref = "src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt" - ) + ){ + "Quaternions and their composition" + } } diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt index 3ef3428c6..85c945faf 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt @@ -16,6 +16,52 @@ import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.structures.MutableMemoryBuffer import kotlin.math.* +/** + * Represents `double`-based quaternion. + * + * @property w The first component. + * @property x The second component. + * @property y The third component. + * @property z The fourth component. + */ +public data class Quaternion( + val w: Double, val x: Double, val y: Double, val z: Double, +) { + init { + require(!w.isNaN()) { "w-component of quaternion is not-a-number" } + require(!x.isNaN()) { "x-component of quaternion is not-a-number" } + require(!y.isNaN()) { "y-component of quaternion is not-a-number" } + require(!z.isNaN()) { "z-component of quaternion is not-a-number" } + } + + /** + * Returns a string representation of this quaternion. + */ + override fun toString(): String = "($w + $x * i + $y * j + $z * k)" + + public companion object : MemorySpec { + override val objectSize: Int + get() = 32 + + override fun MemoryReader.read(offset: Int): Quaternion = + Quaternion(readDouble(offset), readDouble(offset + 8), readDouble(offset + 16), readDouble(offset + 24)) + + override fun MemoryWriter.write(offset: Int, value: Quaternion) { + writeDouble(offset, value.w) + writeDouble(offset + 8, value.x) + writeDouble(offset + 16, value.y) + writeDouble(offset + 24, value.z) + } + } +} + +public fun Quaternion(w: Number, x: Number = 0.0, y: Number = 0.0, z: Number = 0.0): Quaternion = Quaternion( + w.toDouble(), + x.toDouble(), + y.toDouble(), + z.toDouble(), +) + /** * This quaternion's conjugate. */ @@ -45,23 +91,23 @@ public val Quaternion.r: Double @OptIn(UnstableKMathAPI::class) public object QuaternionField : Field, Norm, PowerOperations, ExponentialOperations, NumbersAddOps, ScaleOperations { - override val zero: Quaternion = 0.toQuaternion() - override val one: Quaternion = 1.toQuaternion() + override val zero: Quaternion = Quaternion(0.0) + override val one: Quaternion = Quaternion(1.0) /** * The `i` quaternion unit. */ - public val i: Quaternion = Quaternion(0, 1) + public val i: Quaternion = Quaternion(0.0, 1.0, 0.0, 0.0) /** * The `j` quaternion unit. */ - public val j: Quaternion = Quaternion(0, 0, 1) + public val j: Quaternion = Quaternion(0.0, 0.0, 1.0, 0.0) /** * The `k` quaternion unit. */ - public val k: Quaternion = Quaternion(0, 0, 0, 1) + public val k: Quaternion = Quaternion(0.0, 0.0, 0.0, 1.0) override fun add(left: Quaternion, right: Quaternion): Quaternion = Quaternion(left.w + right.w, left.x + right.x, left.y + right.y, left.z + right.z) @@ -133,7 +179,7 @@ public object QuaternionField : Field, Norm, override fun exp(arg: Quaternion): Quaternion { val un = arg.x * arg.x + arg.y * arg.y + arg.z * arg.z - if (un == 0.0) return exp(arg.w).toQuaternion() + if (un == 0.0) return Quaternion(exp(arg.w)) val n1 = sqrt(un) val ea = exp(arg.w) val n2 = ea * sin(n1) / n1 @@ -158,7 +204,8 @@ public object QuaternionField : Field, Norm, return Quaternion(ln(n), th * arg.x, th * arg.y, th * arg.z) } - override operator fun Number.plus(other: Quaternion): Quaternion = Quaternion(toDouble() + other.w, other.x, other.y, other.z) + override operator fun Number.plus(other: Quaternion): Quaternion = + Quaternion(toDouble() + other.w, other.x, other.y, other.z) override operator fun Number.minus(other: Quaternion): Quaternion = Quaternion(toDouble() - other.w, -other.x, -other.y, -other.z) @@ -179,7 +226,7 @@ public object QuaternionField : Field, Norm, else -> null } - override fun number(value: Number): Quaternion = value.toQuaternion() + override fun number(value: Number): Quaternion = Quaternion(value) override fun sinh(arg: Quaternion): Quaternion = (exp(arg) - exp(-arg)) / 2.0 override fun cosh(arg: Quaternion): Quaternion = (exp(arg) + exp(-arg)) / 2.0 @@ -189,76 +236,6 @@ public object QuaternionField : Field, Norm, override fun atanh(arg: Quaternion): Quaternion = (ln(arg + one) - ln(one - arg)) / 2.0 } -/** - * Represents `double`-based quaternion. - * - * @property w The first component. - * @property x The second component. - * @property y The third component. - * @property z The fourth component. - */ -@OptIn(UnstableKMathAPI::class) -public data class Quaternion( - val w: Double, val x: Double, val y: Double, val z: Double, -) { - public constructor(w: Number, x: Number, y: Number, z: Number) : this( - w.toDouble(), - x.toDouble(), - y.toDouble(), - z.toDouble(), - ) - - public constructor(w: Number, x: Number, y: Number) : this(w.toDouble(), x.toDouble(), y.toDouble(), 0.0) - public constructor(w: Number, x: Number) : this(w.toDouble(), x.toDouble(), 0.0, 0.0) - public constructor(w: Number) : this(w.toDouble(), 0.0, 0.0, 0.0) - public constructor(wx: Complex, yz: Complex) : this(wx.re, wx.im, yz.re, yz.im) - public constructor(wx: Complex) : this(wx.re, wx.im, 0, 0) - - init { - require(!w.isNaN()) { "w-component of quaternion is not-a-number" } - require(!x.isNaN()) { "x-component of quaternion is not-a-number" } - require(!y.isNaN()) { "x-component of quaternion is not-a-number" } - require(!z.isNaN()) { "x-component of quaternion is not-a-number" } - } - - /** - * Returns a string representation of this quaternion. - */ - override fun toString(): String = "($w + $x * i + $y * j + $z * k)" - - public companion object : MemorySpec { - override val objectSize: Int - get() = 32 - - override fun MemoryReader.read(offset: Int): Quaternion = - Quaternion(readDouble(offset), readDouble(offset + 8), readDouble(offset + 16), readDouble(offset + 24)) - - override fun MemoryWriter.write(offset: Int, value: Quaternion) { - writeDouble(offset, value.w) - writeDouble(offset + 8, value.x) - writeDouble(offset + 16, value.y) - writeDouble(offset + 24, value.z) - } - } -} - -/** - * Creates a quaternion with real part equal to this real. - * - * @receiver the real part. - * @return a new quaternion. - */ -public fun Number.toQuaternion(): Quaternion = Quaternion(this) - -/** - * Creates a quaternion with `w`-component equal to `re`-component of given complex and `x`-component equal to - * `im`-component of given complex. - * - * @receiver the complex number. - * @return a new quaternion. - */ -public fun Complex.toQuaternion(): Quaternion = Quaternion(this) - /** * Creates a new buffer of quaternions with the specified [size], where each element is calculated by calling the * specified [init] function. diff --git a/kmath-geometry/build.gradle.kts b/kmath-geometry/build.gradle.kts index 7eb814683..bfe2e32a2 100644 --- a/kmath-geometry/build.gradle.kts +++ b/kmath-geometry/build.gradle.kts @@ -6,7 +6,7 @@ plugins { kotlin.sourceSets.commonMain { dependencies { - api(project(":kmath-core")) + api(projects.kmath.kmathComplex) } } diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt index d00575bcc..a83cb3ac7 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 @@ -6,12 +6,10 @@ package space.kscience.kmath.geometry import space.kscience.kmath.linear.Point -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.invoke import kotlin.math.sqrt -@OptIn(UnstableKMathAPI::class) public interface Vector2D : Point, Vector { public val x: Double public val y: Double @@ -29,7 +27,6 @@ public interface Vector2D : Point, Vector { public val Vector2D.r: Double get() = Euclidean2DSpace { norm() } -@Suppress("FunctionName") public fun Vector2D(x: Double, y: Double): Vector2D = Vector2DImpl(x, y) private data class Vector2DImpl( diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt index e12563b46..d3b3fb15e 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 @@ -6,12 +6,10 @@ package space.kscience.kmath.geometry import space.kscience.kmath.linear.Point -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.invoke import kotlin.math.sqrt -@OptIn(UnstableKMathAPI::class) public interface Vector3D : Point, Vector { public val x: Double public val y: Double -- 2.34.1 From 5928adfe45fc4b1d608e94fb5b2c12c447377c24 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Mon, 13 Jun 2022 12:08:58 +0300 Subject: [PATCH 090/275] Fixed merging accidents. --- .../kscience/kmath/functions/Piecewise.kt | 132 ++++++++++++++++++ .../kmath/integration/SplineIntegrator.kt | 112 +++++++++++++++ .../kmath/interpolation/Interpolator.kt | 92 ++++++++++++ .../kmath/interpolation/LinearInterpolator.kt | 43 ++++++ .../kmath/interpolation/SplineInterpolator.kt | 88 ++++++++++++ .../kmath/integration/SplineIntegralTest.kt | 48 +++++++ .../interpolation/LinearInterpolatorTest.kt | 29 ++++ .../interpolation/SplineInterpolatorTest.kt | 36 +++++ 8 files changed, 580 insertions(+) create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt new file mode 100644 index 000000000..612b00535 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt @@ -0,0 +1,132 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.operations.Ring + +/** + * Represents piecewise-defined function. + * + * @param T the piece key type. + * @param R the sub-function type. + */ +public fun interface Piecewise { + /** + * Returns the appropriate sub-function for given piece key. + */ + public fun findPiece(arg: T): R? +} + +/** + * Represents piecewise-defined function where all the sub-functions are polynomials. + * + * @property pieces An ordered list of range-polynomial pairs. The list does not in general guarantee that there are no + * "holes" in it. + */ +public interface PiecewisePolynomial> : Piecewise> { + public val pieces: Collection, ListPolynomial>> + + override fun findPiece(arg: T): ListPolynomial? +} + +/** + * A generic piecewise without constraints on how pieces are placed + */ +@PerformancePitfall("findPiece method of resulting piecewise is slow") +public fun > PiecewisePolynomial( + pieces: Collection, ListPolynomial>>, +): PiecewisePolynomial = object : PiecewisePolynomial { + override val pieces: Collection, ListPolynomial>> = pieces + + override fun findPiece(arg: T): ListPolynomial? = pieces.firstOrNull { arg in it.first }?.second +} + +/** + * An optimized piecewise that uses not separate pieces, but a range separated by delimiters. + * The pieces search is logarithmic. + */ +private class OrderedPiecewisePolynomial>( + override val pieces: List, ListPolynomial>>, +) : PiecewisePolynomial { + + override fun findPiece(arg: T): ListPolynomial? { + val index = pieces.binarySearch { (range, _) -> + when { + arg >= range.endInclusive -> -1 + arg < range.start -> +1 + else -> 0 + } + } + return if (index < 0) null else pieces[index].second + } + +} + +/** + * A [Piecewise] builder where all the pieces are ordered by the [Comparable] type instances. + * + * @param T the comparable piece key type. + * @param delimiter the initial piecewise separator + */ +public class PiecewiseBuilder>(delimiter: T) { + private val delimiters: MutableList = arrayListOf(delimiter) + private val pieces: MutableList> = arrayListOf() + + /** + * Dynamically adds a piece to the right side (beyond maximum argument value of previous piece) + * + * @param right new rightmost position. If is less than current rightmost position, an error is thrown. + * @param piece the sub-function. + */ + public fun putRight(right: T, piece: ListPolynomial) { + require(right > delimiters.last()) { "New delimiter should be to the right of old one" } + delimiters += right + pieces += piece + } + + /** + * Dynamically adds a piece to the left side (beyond maximum argument value of previous piece) + * + * @param left the new leftmost position. If is less than current rightmost position, an error is thrown. + * @param piece the sub-function. + */ + public fun putLeft(left: T, piece: ListPolynomial) { + require(left < delimiters.first()) { "New delimiter should be to the left of old one" } + delimiters.add(0, left) + pieces.add(0, piece) + } + + public fun build(): PiecewisePolynomial = OrderedPiecewisePolynomial(delimiters.zipWithNext { l, r -> + l..r + }.zip(pieces)) +} + +/** + * A builder for [PiecewisePolynomial] + */ +public fun > PiecewisePolynomial( + startingPoint: T, + builder: PiecewiseBuilder.() -> Unit, +): PiecewisePolynomial = PiecewiseBuilder(startingPoint).apply(builder).build() + +/** + * Return a value of polynomial function with given [ring] a given [arg] or null if argument is outside piecewise + * definition. + */ +public fun , C : Ring> PiecewisePolynomial.substitute(ring: C, arg: T): T? = + findPiece(arg)?.substitute(ring, arg) + +/** + * Convert this polynomial to a function returning nullable value (null if argument is outside piecewise range). + */ +public fun , C : Ring> PiecewisePolynomial.asFunction(ring: C): (T) -> T? = { substitute(ring, it) } + +/** + * Convert this polynomial to a function using [defaultValue] for arguments outside the piecewise range. + */ +public fun , C : Ring> PiecewisePolynomial.asFunction(ring: C, defaultValue: T): (T) -> T = + { substitute(ring, it) ?: defaultValue } 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 new file mode 100644 index 000000000..80006c2de --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt @@ -0,0 +1,112 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.integration + +import space.kscience.kmath.functions.PiecewisePolynomial +import space.kscience.kmath.functions.integrate +import space.kscience.kmath.functions.antiderivative +import space.kscience.kmath.interpolation.PolynomialInterpolator +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.structures.Buffer +import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.structures.MutableBufferFactory + +/** + * Compute analytical indefinite integral of this [PiecewisePolynomial], keeping all intervals intact + */ +@OptIn(PerformancePitfall::class) +@UnstableKMathAPI +public fun > PiecewisePolynomial.integrate(algebra: Field): PiecewisePolynomial = + PiecewisePolynomial(pieces.map { it.first to it.second.antiderivative(algebra) }) + +/** + * Compute definite integral of given [PiecewisePolynomial] piece by piece in a given [range] + * Requires [UnivariateIntegrationNodes] or [IntegrationRange] and [IntegrandMaxCalls] + * + * TODO use context receiver for algebra + */ +@UnstableKMathAPI +public fun > PiecewisePolynomial.integrate( + algebra: Field, range: ClosedRange, +): T = algebra.sum( + pieces.map { (region, poly) -> + val intersectedRange = maxOf(range.start, region.start)..minOf(range.endInclusive, region.endInclusive) + //Check if polynomial range is not used + if (intersectedRange.start == intersectedRange.endInclusive) algebra.zero + else poly.integrate(algebra, intersectedRange) + } +) + +/** + * A generic spline-interpolation-based analytic integration + * * [IntegrationRange]—the univariate range of integration. By default, uses `0..1` interval. + * * [IntegrandMaxCalls]—the maximum number of function calls during integration. For non-iterative rules, always uses + * the maximum number of points. By default, uses 10 points. + */ +@UnstableKMathAPI +public class SplineIntegrator>( + public val algebra: Field, + public val bufferFactory: MutableBufferFactory, +) : UnivariateIntegrator { + override fun process(integrand: UnivariateIntegrand): UnivariateIntegrand = algebra { + val range = integrand.getFeature()?.range ?: 0.0..1.0 + + val interpolator: PolynomialInterpolator = SplineInterpolator(algebra, bufferFactory) + + val nodes: Buffer = integrand.getFeature()?.nodes ?: run { + val numPoints = integrand.getFeature()?.maxCalls ?: 100 + val step = (range.endInclusive - range.start) / (numPoints - 1) + DoubleBuffer(numPoints) { i -> range.start + i * step } + } + + val values = nodes.map(bufferFactory) { integrand.function(it) } + val polynomials = interpolator.interpolatePolynomials( + nodes.map(bufferFactory) { number(it) }, + values + ) + val res = polynomials.integrate(algebra, number(range.start)..number(range.endInclusive)) + integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + nodes.size) + } +} + +/** + * A simplified double-based spline-interpolation-based analytic integration + * * [IntegrationRange]—the univariate range of integration. By default, uses `0.0..1.0` interval. + * * [IntegrandMaxCalls]—the maximum number of function calls during integration. For non-iterative rules, always + * uses the maximum number of points. By default, uses 10 points. + */ +@UnstableKMathAPI +public object DoubleSplineIntegrator : UnivariateIntegrator { + override fun process(integrand: UnivariateIntegrand): UnivariateIntegrand { + val range = integrand.getFeature()?.range ?: 0.0..1.0 + val interpolator: PolynomialInterpolator = SplineInterpolator(DoubleField, ::DoubleBuffer) + + val nodes: Buffer = integrand.getFeature()?.nodes ?: run { + val numPoints = integrand.getFeature()?.maxCalls ?: 100 + val step = (range.endInclusive - range.start) / (numPoints - 1) + DoubleBuffer(numPoints) { i -> range.start + i * step } + } + + val values = nodes.map { integrand.function(it) } + val polynomials = interpolator.interpolatePolynomials(nodes, values) + val res = polynomials.integrate(DoubleField, range) + return integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + nodes.size) + } +} + +@Suppress("unused") +@UnstableKMathAPI +public inline val DoubleField.splineIntegrator: UnivariateIntegrator + get() = DoubleSplineIntegrator \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt new file mode 100644 index 000000000..62819be0c --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt @@ -0,0 +1,92 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +@file:OptIn(UnstableKMathAPI::class) + +package space.kscience.kmath.interpolation + +import space.kscience.kmath.data.XYColumnarData +import space.kscience.kmath.functions.PiecewisePolynomial +import space.kscience.kmath.functions.asFunction +import space.kscience.kmath.functions.substitute +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.asBuffer + +/** + * And interpolator for data with x column type [X], y column type [Y]. + */ +public fun interface Interpolator { + public fun interpolate(points: XYColumnarData): (X) -> Y +} + +/** + * And interpolator returning [PiecewisePolynomial] function + */ +public interface PolynomialInterpolator> : Interpolator { + public val algebra: Ring + + public fun getDefaultValue(): T = error("Out of bounds") + + public fun interpolatePolynomials(points: XYColumnarData): PiecewisePolynomial + + override fun interpolate(points: XYColumnarData): (T) -> T = { x -> + interpolatePolynomials(points).substitute(algebra, x) ?: getDefaultValue() + } +} + + +public fun > PolynomialInterpolator.interpolatePolynomials( + x: Buffer, + y: Buffer, +): PiecewisePolynomial { + val pointSet = XYColumnarData.of(x, y) + return interpolatePolynomials(pointSet) +} + +public fun > PolynomialInterpolator.interpolatePolynomials( + data: Map, +): PiecewisePolynomial { + val pointSet = XYColumnarData.of(data.keys.toList().asBuffer(), data.values.toList().asBuffer()) + return interpolatePolynomials(pointSet) +} + +public fun > PolynomialInterpolator.interpolatePolynomials( + data: List>, +): PiecewisePolynomial { + val pointSet = XYColumnarData.of(data.map { it.first }.asBuffer(), data.map { it.second }.asBuffer()) + return interpolatePolynomials(pointSet) +} + +public fun > PolynomialInterpolator.interpolate( + x: Buffer, + y: Buffer, +): (T) -> T? = interpolatePolynomials(x, y).asFunction(algebra) + +public fun > PolynomialInterpolator.interpolate( + data: Map, +): (T) -> T? = interpolatePolynomials(data).asFunction(algebra) + +public fun > PolynomialInterpolator.interpolate( + data: List>, +): (T) -> T? = interpolatePolynomials(data).asFunction(algebra) + + +public fun > PolynomialInterpolator.interpolate( + x: Buffer, + y: Buffer, + defaultValue: T, +): (T) -> T = interpolatePolynomials(x, y).asFunction(algebra, defaultValue) + +public fun > PolynomialInterpolator.interpolate( + data: Map, + defaultValue: T, +): (T) -> T = interpolatePolynomials(data).asFunction(algebra, defaultValue) + +public fun > PolynomialInterpolator.interpolate( + data: List>, + defaultValue: T, +): (T) -> T = interpolatePolynomials(data).asFunction(algebra, defaultValue) \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt new file mode 100644 index 000000000..b55f16cf2 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.interpolation + +import space.kscience.kmath.data.XYColumnarData +import space.kscience.kmath.functions.PiecewisePolynomial +import space.kscience.kmath.functions.ListPolynomial +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.Field +import space.kscience.kmath.operations.invoke + +@OptIn(UnstableKMathAPI::class) +internal fun > insureSorted(points: XYColumnarData<*, T, *>) { + for (i in 0 until points.size - 1) + require(points.x[i + 1] > points.x[i]) { "Input data is not sorted at index $i" } +} + +/** + * Reference JVM implementation: https://github.com/apache/commons-math/blob/master/src/main/java/org/apache/commons/math4/analysis/interpolation/LinearInterpolator.java + */ +public class LinearInterpolator>(override val algebra: Field) : PolynomialInterpolator { + + @OptIn(UnstableKMathAPI::class) + override fun interpolatePolynomials(points: XYColumnarData): PiecewisePolynomial = algebra { + require(points.size > 0) { "Point array should not be empty" } + insureSorted(points) + + PiecewisePolynomial(points.x[0]) { + for (i in 0 until points.size - 1) { + val slope = (points.y[i + 1] - points.y[i]) / (points.x[i + 1] - points.x[i]) + val const = points.y[i] - slope * points.x[i] + val polynomial = ListPolynomial(const, slope) + putRight(points.x[i + 1], polynomial) + } + } + } +} + +public val > Field.linearInterpolator: LinearInterpolator + get() = LinearInterpolator(this) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt new file mode 100644 index 000000000..0bcbfd0c6 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt @@ -0,0 +1,88 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.interpolation + +import space.kscience.kmath.data.XYColumnarData +import space.kscience.kmath.functions.PiecewisePolynomial +import space.kscience.kmath.functions.ListPolynomial +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.structures.DoubleBuffer +import space.kscience.kmath.structures.MutableBufferFactory + +/** + * Generic spline interpolator. Not recommended for performance critical places, use platform-specific and type + * specific ones. + * + * Based on + * https://github.com/apache/commons-math/blob/eb57d6d457002a0bb5336d789a3381a24599affe/src/main/java/org/apache/commons/math4/analysis/interpolation/SplineInterpolator.java + */ +public class SplineInterpolator>( + override val algebra: Field, + public val bufferFactory: MutableBufferFactory, +) : PolynomialInterpolator { + //TODO possibly optimize zeroed buffers + + @OptIn(UnstableKMathAPI::class) + override fun interpolatePolynomials(points: XYColumnarData): PiecewisePolynomial = algebra { + require(points.size >= 3) { "Can't use spline interpolator with less than 3 points" } + insureSorted(points) + // Number of intervals. The number of data points is n + 1. + val n = points.size - 1 + // Differences between knot points + val h = bufferFactory(n) { i -> points.x[i + 1] - points.x[i] } + val mu = bufferFactory(n) { zero } + val z = bufferFactory(n + 1) { zero } + + for (i in 1 until n) { + val g = 2.0 * (points.x[i + 1] - points.x[i - 1]) - h[i - 1] * mu[i - 1] + mu[i] = h[i] / g + z[i] = + ((points.y[i + 1] * h[i - 1] - points.y[i] * (points.x[i + 1] - points.x[i - 1]) + points.y[i - 1] * h[i]) * 3.0 / + (h[i - 1] * h[i]) - h[i - 1] * z[i - 1]) / g + } + + // cubic spline coefficients -- b is linear, c quadratic, d is cubic (original y's are constants) + + PiecewisePolynomial(points.x[points.size - 1]) { + var cOld = zero + + for (j in n - 1 downTo 0) { + val c = z[j] - mu[j] * cOld + val a = points.y[j] + val b = (points.y[j + 1] - points.y[j]) / h[j] - h[j] * (cOld + 2.0 * c) / 3.0 + val d = (cOld - c) / (3.0 * h[j]) + val x0 = points.x[j] + val x02 = x0 * x0 + val x03 = x02 * x0 + //Shift coefficients to represent absolute polynomial instead of one with an offset + val polynomial = ListPolynomial( + a - b * x0 + c * x02 - d * x03, + b - 2 * c * x0 + 3 * d * x02, + c - 3 * d * x0, + d + ) + cOld = c + putLeft(x0, polynomial) + } + } + } +} + + +public fun > Field.splineInterpolator( + bufferFactory: MutableBufferFactory, +): SplineInterpolator = SplineInterpolator(this, bufferFactory) + +public val DoubleField.splineInterpolator: SplineInterpolator + get() = SplineInterpolator(this, ::DoubleBuffer) \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt new file mode 100644 index 000000000..aae0ad017 --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.integration + +import space.kscience.kmath.functions.ListPolynomial +import space.kscience.kmath.functions.integrate +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.DoubleField +import kotlin.math.PI +import kotlin.math.sin +import kotlin.test.Test +import kotlin.test.assertEquals + +@OptIn(UnstableKMathAPI::class) +class SplineIntegralTest { + + @Test + fun integratePolynomial(){ + val polynomial = ListPolynomial(1.0, 2.0, 3.0) + val integral = polynomial.integrate(DoubleField,1.0..2.0) + assertEquals(11.0, integral, 0.001) + } + + @Test + fun gaussSin() { + val res = DoubleField.splineIntegrator.integrate(0.0..2 * PI, IntegrandMaxCalls(5)) { x -> + sin(x) + } + assertEquals(0.0, res.value, 1e-2) + } + + @Test + fun gaussUniform() { + val res = DoubleField.splineIntegrator.integrate(35.0..100.0, IntegrandMaxCalls(20)) { x -> + if(x in 30.0..50.0){ + 1.0 + } else { + 0.0 + } + } + assertEquals(15.0, res.value, 0.5) + } + + +} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt new file mode 100644 index 000000000..1143036d4 --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.interpolation + +import space.kscience.kmath.operations.DoubleField +import kotlin.test.Test +import kotlin.test.assertEquals + +internal class LinearInterpolatorTest { + @Test + fun testInterpolation() { + val data = listOf( + 0.0 to 0.0, + 1.0 to 1.0, + 2.0 to 3.0, + 3.0 to 4.0 + ) + + //val polynomial: PiecewisePolynomial = DoubleField.linearInterpolator.interpolatePolynomials(data) + val function = DoubleField.linearInterpolator.interpolate(data) + assertEquals(null, function(-1.0)) + assertEquals(0.5, function(0.5)) + assertEquals(2.0, function(1.5)) + assertEquals(3.0, function(2.0)) + } +} diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt new file mode 100644 index 000000000..f748535e2 --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.interpolation + +import space.kscience.kmath.operations.DoubleField +import kotlin.math.PI +import kotlin.math.sin +import kotlin.test.Test +import kotlin.test.assertEquals + +internal class SplineInterpolatorTest { + @Test + fun testInterpolation() { + val data = (0..10).map { + val x = it.toDouble() / 5 * PI + x to sin(x) + } + + //val polynomial: PiecewisePolynomial = DoubleField.splineInterpolator.interpolatePolynomials(data) + + val function = DoubleField.splineInterpolator.interpolate(data, Double.NaN) + + assertEquals(Double.NaN, function(-1.0)) + assertEquals(sin(0.5), function(0.5), 0.1) + assertEquals(sin(1.5), function(1.5), 0.1) + assertEquals(sin(2.0), function(2.0), 0.1) + } +} -- 2.34.1 From 58e0715714487323a46f5b86e121a46782d356c5 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Mon, 13 Jun 2022 12:15:14 +0300 Subject: [PATCH 091/275] Removed duplicates of copyright comments. --- .../space/kscience/kmath/integration/SplineIntegrator.kt | 5 ----- .../space/kscience/kmath/interpolation/SplineInterpolator.kt | 5 ----- .../kscience/kmath/interpolation/SplineInterpolatorTest.kt | 5 ----- 3 files changed, 15 deletions(-) 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 80006c2de..0fcd4c6e5 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 @@ -3,11 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - package space.kscience.kmath.integration import space.kscience.kmath.functions.PiecewisePolynomial diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt index 0bcbfd0c6..48c90ff23 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt @@ -3,11 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - package space.kscience.kmath.interpolation import space.kscience.kmath.data.XYColumnarData diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt index f748535e2..4c7d816d4 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt @@ -3,11 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - package space.kscience.kmath.interpolation import space.kscience.kmath.operations.DoubleField -- 2.34.1 From 85a1e8b33f3ed3683d1e68e722ef0cf89fc43cc5 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 14 Jun 2022 16:27:32 +0300 Subject: [PATCH 092/275] New common test infrastructure --- build.gradle.kts | 14 ++- .../kscience/kmath/complex/Quaternion.kt | 79 ++++++++++---- ...aternionFieldTest.kt => QuaternionTest.kt} | 15 ++- .../kmath/geometry/Euclidean3DSpace.kt | 14 +++ .../{Projections.kt => projections.kt} | 2 + .../kscience/kmath/geometry/rotations3D.kt | 100 ++++++++++++++++++ .../kscience/kmath/geometry/RotationTest.kt | 35 ++++++ .../tensorflow/DoubleTensorFlowAlgebra.kt | 2 + settings.gradle.kts | 1 + test-utils/build.gradle.kts | 13 +++ .../commonMain/kotlin}/AlgebraicVerifier.kt | 0 .../src/commonMain/kotlin}/FieldVerifier.kt | 2 +- .../src/commonMain/kotlin}/RingVerifier.kt | 2 +- .../src/commonMain/kotlin}/SpaceVerifier.kt | 10 +- test-utils/src/commonMain/kotlin/asserts.kt | 20 ++++ 15 files changed, 279 insertions(+), 30 deletions(-) rename kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/{QuaternionFieldTest.kt => QuaternionTest.kt} (84%) rename kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/{Projections.kt => projections.kt} (97%) create mode 100644 kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/rotations3D.kt create mode 100644 kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt create mode 100644 test-utils/build.gradle.kts rename {kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils => test-utils/src/commonMain/kotlin}/AlgebraicVerifier.kt (100%) rename {kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils => test-utils/src/commonMain/kotlin}/FieldVerifier.kt (96%) rename {kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils => test-utils/src/commonMain/kotlin}/RingVerifier.kt (95%) rename {kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils => test-utils/src/commonMain/kotlin}/SpaceVerifier.kt (93%) create mode 100644 test-utils/src/commonMain/kotlin/asserts.kt diff --git a/build.gradle.kts b/build.gradle.kts index ab136bfbc..d8c591799 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -17,7 +17,7 @@ allprojects { subprojects { if (name.startsWith("kmath")) apply() - plugins.withId("org.jetbrains.dokka"){ + plugins.withId("org.jetbrains.dokka") { tasks.withType { dependsOn(tasks["assemble"]) @@ -51,6 +51,18 @@ subprojects { } } } + + plugins.withId("org.jetbrains.kotlin.multiplatform") { + configure { + sourceSets { + val commonTest by getting { + dependencies { + implementation(projects.testUtils) + } + } + } + } + } } readme.readmeTemplate = file("docs/templates/README-TEMPLATE.md") diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt index 85c945faf..359b66b20 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt @@ -24,9 +24,12 @@ import kotlin.math.* * @property y The third component. * @property z The fourth component. */ -public data class Quaternion( - val w: Double, val x: Double, val y: Double, val z: Double, -) { +public class Quaternion( + public val w: Double, + public val x: Double, + public val y: Double, + public val z: Double, +) : Buffer { init { require(!w.isNaN()) { "w-component of quaternion is not-a-number" } require(!x.isNaN()) { "x-component of quaternion is not-a-number" } @@ -39,12 +42,49 @@ public data class Quaternion( */ override fun toString(): String = "($w + $x * i + $y * j + $z * k)" - public companion object : MemorySpec { - override val objectSize: Int - get() = 32 + override val size: Int get() = 4 - override fun MemoryReader.read(offset: Int): Quaternion = - Quaternion(readDouble(offset), readDouble(offset + 8), readDouble(offset + 16), readDouble(offset + 24)) + override fun get(index: Int): Double = when (index) { + 0 -> w + 1 -> x + 2 -> y + 3 -> z + else -> error("Index $index out of bounds [0,3]") + } + + override fun iterator(): Iterator = listOf(w, x, y, z).iterator() + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other == null || this::class != other::class) return false + + other as Quaternion + + if (w != other.w) return false + if (x != other.x) return false + if (y != other.y) return false + if (z != other.z) return false + + return true + } + + override fun hashCode(): Int { + var result = w.hashCode() + result = 31 * result + x.hashCode() + result = 31 * result + y.hashCode() + result = 31 * result + z.hashCode() + return result + } + + public companion object : MemorySpec { + override val objectSize: Int get() = 32 + + override fun MemoryReader.read(offset: Int): Quaternion = Quaternion( + readDouble(offset), + readDouble(offset + 8), + readDouble(offset + 16), + readDouble(offset + 24) + ) override fun MemoryWriter.write(offset: Int, value: Quaternion) { writeDouble(offset, value.w) @@ -66,30 +106,22 @@ public fun Quaternion(w: Number, x: Number = 0.0, y: Number = 0.0, z: Number = 0 * This quaternion's conjugate. */ public val Quaternion.conjugate: Quaternion - get() = QuaternionField { z - x * i - y * j - z * k } + get() = Quaternion(w, -x, -y, -z) /** * This quaternion's reciprocal. */ public val Quaternion.reciprocal: Quaternion get() { - QuaternionField { - val n = norm(this@reciprocal) - return conjugate / (n * n) - } + val norm2 = (w * w + x * x + y * y + z * z) + return Quaternion(w / norm2, -x / norm2, -y / norm2, -z / norm2) } -/** - * Absolute value of the quaternion. - */ -public val Quaternion.r: Double - get() = sqrt(w * w + x * x + y * y + z * z) - /** * A field of [Quaternion]. */ @OptIn(UnstableKMathAPI::class) -public object QuaternionField : Field, Norm, PowerOperations, +public object QuaternionField : Field, Norm, PowerOperations, ExponentialOperations, NumbersAddOps, ScaleOperations { override val zero: Quaternion = Quaternion(0.0) override val one: Quaternion = Quaternion(1.0) @@ -217,7 +249,12 @@ public object QuaternionField : Field, Norm, Quaternion(toDouble() * arg.w, toDouble() * arg.x, toDouble() * arg.y, toDouble() * arg.z) override fun Quaternion.unaryMinus(): Quaternion = Quaternion(-w, -x, -y, -z) - override fun norm(arg: Quaternion): Quaternion = sqrt(arg.conjugate * arg) + override fun norm(arg: Quaternion): Double = sqrt( + arg.w.pow(2) + + arg.x.pow(2) + + arg.y.pow(2) + + arg.z.pow(2) + ) override fun bindSymbolOrNull(value: String): Quaternion? = when (value) { "i" -> i diff --git a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/QuaternionFieldTest.kt b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/QuaternionTest.kt similarity index 84% rename from kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/QuaternionFieldTest.kt rename to kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/QuaternionTest.kt index 6784f3516..fd4df736c 100644 --- a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/QuaternionFieldTest.kt +++ b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/QuaternionTest.kt @@ -6,10 +6,23 @@ package space.kscience.kmath.complex import space.kscience.kmath.operations.invoke +import space.kscience.kmath.testutils.assertBufferEquals import kotlin.test.Test import kotlin.test.assertEquals -internal class QuaternionFieldTest { +internal class QuaternionTest { + + @Test + fun testNorm() { + assertEquals(2.0, QuaternionField.norm(Quaternion(1.0, 1.0, 1.0, 1.0))) + } + + @Test + fun testInverse() = QuaternionField { + val q = Quaternion(1.0, 2.0, -3.0, 4.0) + assertBufferEquals(one, q * q.reciprocal, 1e-4) + } + @Test fun testAddition() { assertEquals(Quaternion(42, 42), QuaternionField { Quaternion(16, 16) + Quaternion(26, 26) }) diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt index d3b3fb15e..c1fc74bf1 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 @@ -8,6 +8,7 @@ package space.kscience.kmath.geometry import space.kscience.kmath.linear.Point import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.invoke +import space.kscience.kmath.structures.Buffer import kotlin.math.sqrt public interface Vector3D : Point, Vector { @@ -29,6 +30,19 @@ public interface Vector3D : Point, Vector { @Suppress("FunctionName") public fun Vector3D(x: Double, y: Double, z: Double): Vector3D = Vector3DImpl(x, y, z) +public fun Buffer.asVector3D(): Vector3D = object : Vector3D { + init { + require(this@asVector3D.size == 3) { "Buffer of size 3 is required for Vector3D" } + } + + override val x: Double get() = this@asVector3D[0] + override val y: Double get() = this@asVector3D[1] + override val z: Double get() = this@asVector3D[2] + + override fun toString(): String = this@asVector3D.toString() + +} + public val Vector3D.r: Double get() = Euclidean3DSpace { norm() } private data class Vector3DImpl( diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Projections.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/projections.kt similarity index 97% rename from kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Projections.kt rename to kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/projections.kt index 5e299f450..6ffc43739 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 @@ -5,6 +5,8 @@ package space.kscience.kmath.geometry +//TODO move vector to receiver + /** * Project vector onto a line. * @param vector to project diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/rotations3D.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/rotations3D.kt new file mode 100644 index 000000000..374315610 --- /dev/null +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/rotations3D.kt @@ -0,0 +1,100 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.geometry + +import space.kscience.kmath.complex.Quaternion +import space.kscience.kmath.complex.QuaternionField +import space.kscience.kmath.complex.reciprocal +import space.kscience.kmath.linear.LinearSpace +import space.kscience.kmath.linear.Matrix +import space.kscience.kmath.linear.linearSpace +import space.kscience.kmath.linear.matrix +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.invoke +import kotlin.math.pow +import kotlin.math.sqrt + +internal fun Vector3D.toQuaternion(): Quaternion = Quaternion(0.0, x, y, z) + +/** + * Angle in radians denoted by this quaternion rotation + */ +public val Quaternion.theta: Double get() = kotlin.math.acos(w) * 2 + +/** + * An axis of quaternion rotation + */ +public val Quaternion.vector: Vector3D + get() { + val sint2 = sqrt(1 - w * w) + + return object : Vector3D { + override val x: Double get() = this@vector.x/sint2 + override val y: Double get() = this@vector.y/sint2 + override val z: Double get() = this@vector.z/sint2 + override fun toString(): String = listOf(x, y, z).toString() + } + } + +/** + * Rotate a vector in a [Euclidean3DSpace] + */ +public fun Euclidean3DSpace.rotate(vector: Vector3D, q: Quaternion): Vector3D = with(QuaternionField) { + val p = vector.toQuaternion() + (q * p * q.reciprocal).vector +} + +/** + * Use a composition of quaternions to create a rotation + */ +public fun Euclidean3DSpace.rotate(vector: Vector3D, composition: QuaternionField.() -> Quaternion): Vector3D = + rotate(vector, QuaternionField.composition()) + +public fun Euclidean3DSpace.rotate(vector: Vector3D, matrix: Matrix): Vector3D { + require(matrix.colNum == 3 && matrix.rowNum == 3) { "Square 3x3 rotation matrix is required" } + return with(DoubleField.linearSpace) { matrix.dot(vector).asVector3D() } +} + +/** + * Convert a [Quaternion] to a rotation matrix + */ +@OptIn(UnstableKMathAPI::class) +public fun Quaternion.toRotationMatrix( + linearSpace: LinearSpace = DoubleField.linearSpace, +): Matrix { + val s = QuaternionField.norm(this).pow(-2) + return linearSpace.matrix(3, 3)( + 1.0 - 2 * s * (y * y + z * z), 2 * s * (x * y - z * w), 2 * s * (x * z + y * w), + 2 * s * (x * y + z * w), 1.0 - 2 * s * (x * x + z * z), 2 * s * (y * z - x * w), + 2 * s * (x * z - y * w), 2 * s * (y * z + x * w), 1.0 - 2 * s * (x * x + y * y) + ) +} + +/** + * taken from https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2015/01/matrix-to-quat.pdf + */ +public fun Quaternion.Companion.fromRotationMatrix(matrix: Matrix): Quaternion { + val t: Double + val q = if (matrix[2, 2] < 0) { + if (matrix[0, 0] > matrix[1, 1]) { + t = 1 + matrix[0, 0] - matrix[1, 1] - matrix[2, 2] + Quaternion(t, matrix[0, 1] + matrix[1, 0], matrix[2, 0] + matrix[0, 2], matrix[1, 2] - matrix[2, 1]) + } else { + t = 1 - matrix[0, 0] + matrix[1, 1] - matrix[2, 2] + Quaternion(matrix[0, 1] + matrix[1, 0], t, matrix[1, 2] + matrix[2, 1], matrix[2, 0] - matrix[0, 2]) + } + } else { + if (matrix[0, 0] < -matrix[1, 1]) { + t = 1 - matrix[0, 0] - matrix[1, 1] + matrix[2, 2] + Quaternion(matrix[2, 0] + matrix[0, 2], matrix[1, 2] + matrix[2, 1], t, matrix[0, 1] - matrix[1, 0]) + } else { + t = 1 + matrix[0, 0] + matrix[1, 1] + matrix[2, 2] + Quaternion(matrix[1, 2] - matrix[2, 1], matrix[2, 0] - matrix[0, 2], matrix[0, 1] - matrix[1, 0], t) + } + } + return QuaternionField.invoke { q * (0.5 / sqrt(t)) } +} \ No newline at end of file diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt new file mode 100644 index 000000000..ca7226fb6 --- /dev/null +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.geometry + +import space.kscience.kmath.complex.Quaternion +import space.kscience.kmath.testutils.assertBufferEquals +import kotlin.test.Test +import kotlin.test.assertEquals + +class RotationTest { + + @Test + fun rotations() = with(Euclidean3DSpace) { + val vector = Vector3D(1.0, 1.0, 1.0) + val q = Quaternion(1.0, 2.0, -3.0, 4.0) + val rotatedByQ = rotate(vector, q) + val matrix = q.toRotationMatrix() + val rotatedByM = rotate(vector,matrix) + + assertBufferEquals(rotatedByQ, rotatedByM, 1e-4) + } + + @Test + fun rotationConversion() { + + val q = Quaternion(1.0, 2.0, -3.0, 4.0) + + val matrix = q.toRotationMatrix() + + assertEquals(q, Quaternion.fromRotationMatrix(matrix)) + } +} \ No newline at end of file diff --git a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowAlgebra.kt b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowAlgebra.kt index ecfd8d098..ad7a978a0 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 @@ -7,6 +7,7 @@ import org.tensorflow.op.core.Constant import org.tensorflow.types.TFloat64 import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.DefaultStrides import space.kscience.kmath.nd.Shape import space.kscience.kmath.nd.StructureND @@ -74,6 +75,7 @@ public class DoubleTensorFlowAlgebra internal constructor( * * The resulting tensor is available outside of scope */ +@UnstableKMathAPI public fun DoubleField.produceWithTF( block: DoubleTensorFlowAlgebra.() -> StructureND, ): StructureND = Graph().use { graph -> diff --git a/settings.gradle.kts b/settings.gradle.kts index b14c594b4..e3c621e9a 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -20,6 +20,7 @@ dependencyResolutionManagement { } include( + ":test-utils", ":kmath-memory", ":kmath-complex", ":kmath-core", diff --git a/test-utils/build.gradle.kts b/test-utils/build.gradle.kts new file mode 100644 index 000000000..88c7ea9d0 --- /dev/null +++ b/test-utils/build.gradle.kts @@ -0,0 +1,13 @@ +plugins { + id("ru.mipt.npm.gradle.mpp") + id("ru.mipt.npm.gradle.native") +} + +kotlin.sourceSets { + commonMain { + dependencies { + api(projects.kmath.kmathCore) + api(kotlin("test")) + } + } +} diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/AlgebraicVerifier.kt b/test-utils/src/commonMain/kotlin/AlgebraicVerifier.kt similarity index 100% rename from kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/AlgebraicVerifier.kt rename to test-utils/src/commonMain/kotlin/AlgebraicVerifier.kt diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/FieldVerifier.kt b/test-utils/src/commonMain/kotlin/FieldVerifier.kt similarity index 96% rename from kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/FieldVerifier.kt rename to test-utils/src/commonMain/kotlin/FieldVerifier.kt index 20a7b6a72..f4ca7506b 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/FieldVerifier.kt +++ b/test-utils/src/commonMain/kotlin/FieldVerifier.kt @@ -10,7 +10,7 @@ import space.kscience.kmath.operations.invoke import kotlin.test.assertEquals import kotlin.test.assertNotEquals -internal class FieldVerifier>( +public class FieldVerifier>( algebra: A, a: T, b: T, c: T, x: Number, ) : RingVerifier(algebra, a, b, c, x) { diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/RingVerifier.kt b/test-utils/src/commonMain/kotlin/RingVerifier.kt similarity index 95% rename from kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/RingVerifier.kt rename to test-utils/src/commonMain/kotlin/RingVerifier.kt index daf18834a..14606cb2c 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/RingVerifier.kt +++ b/test-utils/src/commonMain/kotlin/RingVerifier.kt @@ -10,7 +10,7 @@ import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.invoke import kotlin.test.assertEquals -internal open class RingVerifier(algebra: A, a: T, b: T, c: T, x: Number) : +public open class RingVerifier(algebra: A, a: T, b: T, c: T, x: Number) : SpaceVerifier(algebra, a, b, c, x) where A : Ring, A : ScaleOperations { override fun verify() { diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt b/test-utils/src/commonMain/kotlin/SpaceVerifier.kt similarity index 93% rename from kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt rename to test-utils/src/commonMain/kotlin/SpaceVerifier.kt index 951197fc6..d761a3775 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/testutils/SpaceVerifier.kt +++ b/test-utils/src/commonMain/kotlin/SpaceVerifier.kt @@ -11,12 +11,12 @@ import space.kscience.kmath.operations.invoke import kotlin.test.assertEquals import kotlin.test.assertNotEquals -internal open class SpaceVerifier( +public open class SpaceVerifier( override val algebra: S, - val a: T, - val b: T, - val c: T, - val x: Number, + public val a: T, + public val b: T, + public val c: T, + public val x: Number, ) : AlgebraicVerifier> where S : Ring, S : ScaleOperations { override fun verify() { algebra { diff --git a/test-utils/src/commonMain/kotlin/asserts.kt b/test-utils/src/commonMain/kotlin/asserts.kt new file mode 100644 index 000000000..8e7d1ae23 --- /dev/null +++ b/test-utils/src/commonMain/kotlin/asserts.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.testutils + +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.indices +import kotlin.test.assertEquals +import kotlin.test.fail + +public fun assertBufferEquals(expected: Buffer, result: Buffer, tolerance: Double = 1e-4) { + if (expected.size != result.size) { + fail("Expected size is ${expected.size}, but the result size is ${result.size}") + } + expected.indices.forEach { + assertEquals(expected[it], result[it], tolerance) + } +} \ No newline at end of file -- 2.34.1 From b09127f090c2b9df283eae2bbf689a38bae9b8f0 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 14 Jun 2022 22:52:47 +0700 Subject: [PATCH 093/275] Fix name clash in strict mode; replace eval with new Function --- .../space/kscience/kmath/estree/estree.kt | 2 +- .../kmath/estree/internal/ESTreeBuilder.kt | 28 +++++++------------ .../internal/estree/estree.extensions.kt | 5 +++- 3 files changed, 15 insertions(+), 20 deletions(-) diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt index a8b1aa2e1..240acf1d7 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt @@ -36,7 +36,7 @@ public fun MST.compileToExpression(algebra: Algebra): Expression ) } - return ESTreeBuilder { visit(typed) }.instance + return ESTreeBuilder { visit(typed) }.instance } /** diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt index 40c446da0..16a59d273 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt @@ -14,37 +14,28 @@ internal class ESTreeBuilder(val bodyCallback: ESTreeBuilder.() -> BaseExp private class GeneratedExpression(val executable: dynamic, val constants: Array) : Expression { @Suppress("UNUSED_VARIABLE") override fun invoke(arguments: Map): T { - //val e = executable - //val c = constants + val e = executable + val c = constants val a = js("{}") arguments.forEach { (key, value) -> a[key.identity] = value } - return executable.call(constants, a).unsafeCast() - //return js("e(c, a)").unsafeCast() + return js("e(c, a)").unsafeCast() } } + @Suppress("UNUSED_VARIABLE") val instance: Expression by lazy { val node = Program( sourceType = "script", - VariableDeclaration( - kind = "var", - VariableDeclarator( - id = Identifier("executable"), - init = FunctionExpression( - params = arrayOf(Identifier("constants"), Identifier("arguments")), - body = BlockStatement(ReturnStatement(bodyCallback())), - ), - ), - ), + ReturnStatement(bodyCallback()) ) - eval(generate(node)) - GeneratedExpression(js("executable"), constants.toTypedArray()) + val code = generate(node) + GeneratedExpression(js("new Function('constants', 'arguments_0', code)"), constants.toTypedArray()) } private val constants = mutableListOf() - fun constant(value: Any?) = when { + fun constant(value: Any?): BaseExpression = when { value == null || jsTypeOf(value) == "number" || jsTypeOf(value) == "string" || jsTypeOf(value) == "boolean" -> SimpleLiteral(value) @@ -62,7 +53,8 @@ internal class ESTreeBuilder(val bodyCallback: ESTreeBuilder.() -> BaseExp } } - fun variable(name: Symbol): BaseExpression = call(getOrFail, Identifier("arguments"), SimpleLiteral(name.identity)) + fun variable(name: Symbol): BaseExpression = + call(getOrFail, Identifier("arguments_0"), SimpleLiteral(name.identity)) fun call(function: Function, vararg args: BaseExpression): BaseExpression = SimpleCallExpression( optional = false, diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.extensions.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.extensions.kt index 3aa31f921..5b1ce914e 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.extensions.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.extensions.kt @@ -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("unused") + package space.kscience.kmath.internal.estree internal fun Program(sourceType: String, vararg body: dynamic) = object : Program { @@ -28,9 +30,10 @@ internal fun Identifier(name: String) = object : Identifier { override var name = name } -internal fun FunctionExpression(params: Array, body: BlockStatement) = object : FunctionExpression { +internal fun FunctionExpression(id: Identifier?, params: Array, body: BlockStatement) = object : FunctionExpression { override var params = params override var type = "FunctionExpression" + override var id: Identifier? = id override var body = body } -- 2.34.1 From d0134bdbe9eb65b45f3764c775e657ee0186d163 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 14 Jun 2022 19:15:36 +0300 Subject: [PATCH 094/275] Sift 4. Cleaned up "numbered" case. Tests are in progress. --- .../kmath/operations/bufferOperation.kt | 9 + .../kmath/functions/ListPolynomial.kt | 24 +- .../kmath/functions/ListRationalFunction.kt | 34 +- .../kmath/functions/NumberedPolynomial.kt | 429 +++++++++++++++ .../functions/NumberedRationalFunction.kt | 239 ++++++++ .../kmath/functions/RationalFunction.kt | 8 + .../kscience/kmath/functions/listUtil.kt | 43 +- .../kmath/functions/numberedConstructors.kt | 478 ++++++++++++++++ .../kscience/kmath/functions/numberedUtil.kt | 515 ++++++++++++++++++ 9 files changed, 1724 insertions(+), 55 deletions(-) create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/bufferOperation.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/bufferOperation.kt index 31b0c2841..762f08be1 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 @@ -91,6 +91,15 @@ public inline fun Buffer.fold(initial: R, operation: (acc: R, T) return accumulator } +/** + * Fold given buffer according to indexed [operation] + */ +public inline fun Buffer.foldIndexed(initial: R, operation: (index: Int, acc: R, T) -> R): R { + var accumulator = initial + for (index in this.indices) accumulator = operation(index, accumulator, get(index)) + return accumulator +} + /** * Zip two buffers using given [transform]. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt index fce179fc8..42e3f7301 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt @@ -48,8 +48,8 @@ public data class ListPolynomial( } /** - * Arithmetic context for univariate polynomials with coefficients stored as a [List] constructed with the given [ring] - * of constants. + * 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]. @@ -313,6 +313,10 @@ public open class ListPolynomialSpace>( } ) } + /** + * 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). @@ -332,42 +336,42 @@ public open class ListPolynomialSpace>( // 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. + * Evaluates value of [this] polynomial on provided [argument]. */ @Suppress("NOTHING_TO_INLINE") - public inline fun ListPolynomial.substitute(argument: C): C = this.substitute(ring, argument) + public inline fun ListPolynomial.substitute(argument: C): C = substitute(ring, argument) /** * Substitutes provided polynomial [argument] into [this] polynomial. */ @Suppress("NOTHING_TO_INLINE") - public inline fun ListPolynomial.substitute(argument: ListPolynomial): ListPolynomial = this.substitute(ring, argument) + public inline fun ListPolynomial.substitute(argument: ListPolynomial): ListPolynomial = substitute(ring, argument) /** * Represent [this] polynomial as a regular context-less function. */ @Suppress("NOTHING_TO_INLINE") - public inline fun ListPolynomial.asFunction(): (C) -> C = { this.substitute(ring, it) } + public inline fun ListPolynomial.asFunction(): (C) -> C = asFunctionOver(ring) /** * Represent [this] polynomial as a regular context-less function. */ @Suppress("NOTHING_TO_INLINE") - public inline fun ListPolynomial.asFunctionOfConstant(): (C) -> C = { this.substitute(ring, it) } + public inline fun ListPolynomial.asFunctionOfConstant(): (C) -> C = asFunctionOfConstantOver(ring) /** * Represent [this] polynomial as a regular context-less function. */ @Suppress("NOTHING_TO_INLINE") - public inline fun ListPolynomial.asFunctionOfPolynomial(): (ListPolynomial) -> ListPolynomial = { this.substitute(ring, it) } + public inline fun ListPolynomial.asFunctionOfPolynomial(): (ListPolynomial) -> ListPolynomial = asFunctionOfPolynomialOver(ring) /** * Evaluates value of [this] polynomial on provided [argument]. */ @Suppress("NOTHING_TO_INLINE") - public inline operator fun ListPolynomial.invoke(argument: C): C = this.substitute(ring, argument) + public inline operator fun ListPolynomial.invoke(argument: C): C = substitute(ring, argument) /** * Evaluates value of [this] polynomial on provided [argument]. */ @Suppress("NOTHING_TO_INLINE") - public inline operator fun ListPolynomial.invoke(argument: ListPolynomial): ListPolynomial = this.substitute(ring, argument) + public inline operator fun ListPolynomial.invoke(argument: ListPolynomial): ListPolynomial = substitute(ring, argument) } /** diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt index f3e352bcd..e23baa548 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt @@ -9,7 +9,7 @@ import space.kscience.kmath.operations.Ring /** - * Represents rational function that stores its numerator and denominator as [ListPolynomial]s. + * Represents univariate rational function that stores its numerator and denominator as [ListPolynomial]s. */ public data class ListRationalFunction( public override val numerator: ListPolynomial, @@ -56,82 +56,82 @@ public class ListRationalFunctionSpace> ( * Evaluates value of [this] polynomial on provided argument. */ @Suppress("NOTHING_TO_INLINE") - public inline fun ListPolynomial.substitute(argument: C): C = this.substitute(ring, argument) + public inline fun ListPolynomial.substitute(argument: C): C = substitute(ring, argument) /** * Substitutes provided polynomial [argument] into [this] polynomial. */ @Suppress("NOTHING_TO_INLINE") - public inline fun ListPolynomial.substitute(argument: ListPolynomial): ListPolynomial = this.substitute(ring, argument) + public inline fun ListPolynomial.substitute(argument: ListPolynomial): ListPolynomial = substitute(ring, argument) /** * Substitutes provided rational function [argument] into [this] polynomial. */ @Suppress("NOTHING_TO_INLINE") - public inline fun ListPolynomial.substitute(argument: ListRationalFunction): ListRationalFunction = this.substitute(ring, argument) + public inline fun ListPolynomial.substitute(argument: ListRationalFunction): ListRationalFunction = substitute(ring, argument) /** * Substitutes provided polynomial [argument] into [this] rational function. */ @Suppress("NOTHING_TO_INLINE") - public inline fun ListRationalFunction.substitute(argument: ListPolynomial): ListRationalFunction = this.substitute(ring, argument) + public inline fun ListRationalFunction.substitute(argument: ListPolynomial): ListRationalFunction = substitute(ring, argument) /** * Substitutes provided rational function [argument] into [this] rational function. */ @Suppress("NOTHING_TO_INLINE") - public inline fun ListRationalFunction.substitute(argument: ListRationalFunction): ListRationalFunction = this.substitute(ring, argument) + public inline fun ListRationalFunction.substitute(argument: ListRationalFunction): ListRationalFunction = substitute(ring, argument) /** * Represent [this] polynomial as a regular context-less function. */ @Suppress("NOTHING_TO_INLINE") - public inline fun ListPolynomial.asFunction(): (C) -> C = { this.substitute(ring, it) } + public inline fun ListPolynomial.asFunction(): (C) -> C = { substitute(ring, it) } /** * Represent [this] polynomial as a regular context-less function. */ @Suppress("NOTHING_TO_INLINE") - public inline fun ListPolynomial.asFunctionOfConstant(): (C) -> C = { this.substitute(ring, it) } + public inline fun ListPolynomial.asFunctionOfConstant(): (C) -> C = { substitute(ring, it) } /** * Represent [this] polynomial as a regular context-less function. */ @Suppress("NOTHING_TO_INLINE") - public inline fun ListPolynomial.asFunctionOfPolynomial(): (ListPolynomial) -> ListPolynomial = { this.substitute(ring, it) } + public inline fun ListPolynomial.asFunctionOfPolynomial(): (ListPolynomial) -> ListPolynomial = { substitute(ring, it) } /** * Represent [this] polynomial as a regular context-less function. */ @Suppress("NOTHING_TO_INLINE") - public inline fun ListPolynomial.asFunctionOfRationalFunction(): (ListRationalFunction) -> ListRationalFunction = { this.substitute(ring, it) } + public inline fun ListPolynomial.asFunctionOfRationalFunction(): (ListRationalFunction) -> ListRationalFunction = { substitute(ring, it) } /** * Represent [this] rational function as a regular context-less function. */ @Suppress("NOTHING_TO_INLINE") - public inline fun ListRationalFunction.asFunctionOfPolynomial(): (ListPolynomial) -> ListRationalFunction = { this.substitute(ring, it) } + public inline fun ListRationalFunction.asFunctionOfPolynomial(): (ListPolynomial) -> ListRationalFunction = { substitute(ring, it) } /** * Represent [this] rational function as a regular context-less function. */ @Suppress("NOTHING_TO_INLINE") - public inline fun ListRationalFunction.asFunctionOfRationalFunction(): (ListRationalFunction) -> ListRationalFunction = { this.substitute(ring, it) } + public inline fun ListRationalFunction.asFunctionOfRationalFunction(): (ListRationalFunction) -> ListRationalFunction = { substitute(ring, it) } /** * Evaluates value of [this] polynomial on provided argument. */ @Suppress("NOTHING_TO_INLINE") - public inline operator fun ListPolynomial.invoke(argument: C): C = this.substitute(ring, argument) + public inline operator fun ListPolynomial.invoke(argument: C): C = substitute(ring, argument) /** * Evaluates value of [this] polynomial on provided argument. */ @Suppress("NOTHING_TO_INLINE") - public inline operator fun ListPolynomial.invoke(argument: ListPolynomial): ListPolynomial = this.substitute(ring, argument) + public inline operator fun ListPolynomial.invoke(argument: ListPolynomial): ListPolynomial = substitute(ring, argument) /** * Evaluates value of [this] polynomial on provided argument. */ @Suppress("NOTHING_TO_INLINE") - public inline operator fun ListPolynomial.invoke(argument: ListRationalFunction): ListRationalFunction = this.substitute(ring, argument) + public inline operator fun ListPolynomial.invoke(argument: ListRationalFunction): ListRationalFunction = substitute(ring, argument) /** * Evaluates value of [this] rational function on provided argument. */ @Suppress("NOTHING_TO_INLINE") - public inline operator fun ListRationalFunction.invoke(argument: ListPolynomial): ListRationalFunction = this.substitute(ring, argument) + public inline operator fun ListRationalFunction.invoke(argument: ListPolynomial): ListRationalFunction = substitute(ring, argument) /** * Evaluates value of [this] rational function on provided argument. */ @Suppress("NOTHING_TO_INLINE") - public inline operator fun ListRationalFunction.invoke(argument: ListRationalFunction): ListRationalFunction = this.substitute(ring, argument) + public inline operator fun ListRationalFunction.invoke(argument: ListRationalFunction): ListRationalFunction = substitute(ring, argument) } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt new file mode 100644 index 000000000..9304e66da --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -0,0 +1,429 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.structures.Buffer +import kotlin.jvm.JvmName +import kotlin.math.max + + +/** + * Represents univariate 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 pair + * "key-value" in the map, where the value is the coefficients `a` and the key is a list that associates index of + * every variable in the monomial with multiplicity of the variable occurring 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. + */ + public val coefficients: Map, C> +) : Polynomial { + 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 + .toMutableMap() + .apply { + val degs = emptyList() + + this[degs] = getOrElse(degs) { constantZero } + 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 + .toMutableMap() + .apply { + val degs = emptyList() + + this[degs] = getOrElse(degs) { constantZero } - 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 = + if (other == 0) zero + else NumberedPolynomialAsIs( + coefficients + .toMutableMap() + .apply { + for (degs in keys) this[degs] = this[degs]!! * 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 + .toMutableMap() + .apply { + val degs = emptyList() + + this[degs] = this@plus + getOrElse(degs) { constantZero } + } + ) + /** + * 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 = + if (this == 0) other + else + NumberedPolynomialAsIs( + other.coefficients + .toMutableMap() + .apply { + val degs = emptyList() + + this[degs] = this@minus - getOrElse(degs) { constantZero } + } + ) + /** + * 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 = + if (this == 0) zero + else NumberedPolynomialAsIs( + other.coefficients + .toMutableMap() + .apply { + for (degs in keys) this[degs] = this@times * this[degs]!! + } + ) + + /** + * Converts the integer [value] to polynomial. + */ + public override fun number(value: Int): NumberedPolynomial = number(constantNumber(value)) + + /** + * Returns sum of the constant represented as a polynomial and the polynomial. + */ + override operator fun C.plus(other: NumberedPolynomial): NumberedPolynomial = + with(other.coefficients) { + if (isEmpty()) NumberedPolynomialAsIs(mapOf(emptyList() to this@plus)) + else NumberedPolynomialAsIs( + toMutableMap() + .apply { + val degs = emptyList() + + this[degs] = this@plus + getOrElse(degs) { constantZero } + } + ) + } + /** + * Returns difference between the constant represented as a polynomial and the polynomial. + */ + override operator fun C.minus(other: NumberedPolynomial): NumberedPolynomial = + with(other.coefficients) { + if (isEmpty()) NumberedPolynomialAsIs(mapOf(emptyList() to this@minus)) + else NumberedPolynomialAsIs( + toMutableMap() + .apply { + forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } + + val degs = emptyList() + + this[degs] = this@minus - getOrElse(degs) { constantZero } + } + ) + } + /** + * Returns product of the constant represented as a polynomial and the polynomial. + */ + override operator fun C.times(other: NumberedPolynomial): NumberedPolynomial = + NumberedPolynomialAsIs( + other.coefficients + .toMutableMap() + .apply { + for (degs in keys) this[degs] = this@times * this[degs]!! + } + ) + + /** + * Returns sum of the constant represented as a polynomial and the polynomial. + */ + override operator fun NumberedPolynomial.plus(other: C): NumberedPolynomial = + with(coefficients) { + if (isEmpty()) NumberedPolynomialAsIs(mapOf(emptyList() to other)) + else NumberedPolynomialAsIs( + toMutableMap() + .apply { + val degs = emptyList() + + this[degs] = getOrElse(degs) { constantZero } + other + } + ) + } + /** + * Returns difference between the constant represented as a polynomial and the polynomial. + */ + override operator fun NumberedPolynomial.minus(other: C): NumberedPolynomial = + with(coefficients) { + if (isEmpty()) NumberedPolynomialAsIs(mapOf(emptyList() to other)) + else NumberedPolynomialAsIs( + toMutableMap() + .apply { + val degs = emptyList() + + this[degs] = getOrElse(degs) { constantZero } - other + } + ) + } + /** + * Returns product of the constant represented as a polynomial and the polynomial. + */ + override operator fun NumberedPolynomial.times(other: C): NumberedPolynomial = + NumberedPolynomialAsIs( + coefficients + .toMutableMap() + .apply { + for (degs in keys) this[degs] = this[degs]!! * 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( + buildMap(coefficients.size + other.coefficients.size) { + other.coefficients.mapValuesTo(this) { it.value } + other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value } + } + ) + /** + * Returns difference of the polynomials. + */ + override operator fun NumberedPolynomial.minus(other: NumberedPolynomial): NumberedPolynomial = + NumberedPolynomialAsIs( + buildMap(coefficients.size + other.coefficients.size) { + other.coefficients.mapValuesTo(this) { it.value } + other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value } + } + ) + /** + * 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 + this[degs] = if (degs in this) this[degs]!! + c else 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 // 1 * x_1^0 * x_2^0 * ... + ) + ) + } + + /** + * 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.entries.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.entries.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.entries.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.entries.maxOfOrNull { (degs, _) -> degs.getOrElse(variable) { 0u } } ?: 0u + /** + * Counts degree of the polynomial by the specified [variables]. + */ + public fun NumberedPolynomial.degreeBy(variables: Collection): UInt = + coefficients.entries.maxOfOrNull { (degs, _) -> + degs.withIndex().filter { (index, _) -> index in variables }.sumOf { it.value } + } ?: 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. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedPolynomial.substitute(arguments: Map): NumberedPolynomial = substitute(ring, arguments) + /** + * Substitutes provided arguments [arguments] into [this] polynomial. + */ + @Suppress("NOTHING_TO_INLINE") + @JvmName("substitutePolynomial") + public inline fun NumberedPolynomial.substitute(arguments: Map>) : NumberedPolynomial = substitute(ring, arguments) + /** + * Substitutes provided arguments [arguments] into [this] polynomial. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedPolynomial.substitute(arguments: Buffer): NumberedPolynomial = substitute(ring, arguments) + /** + * Substitutes provided arguments [arguments] into [this] polynomial. + */ + @Suppress("NOTHING_TO_INLINE") + @JvmName("substitutePolynomial") + public inline fun NumberedPolynomial.substitute(arguments: Buffer>) : NumberedPolynomial = substitute(ring, arguments) + /** + * Substitutes provided arguments [arguments] into [this] polynomial. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedPolynomial.substituteFully(arguments: Buffer): C = this.substituteFully(ring, arguments) + + /** + * Represent [this] polynomial as a regular context-less function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedPolynomial.asFunction(): (Buffer) -> C = asFunctionOver(ring) + /** + * Represent [this] polynomial as a regular context-less function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedPolynomial.asFunctionOfConstant(): (Buffer) -> C = asFunctionOfConstantOver(ring) + /** + * Represent [this] polynomial as a regular context-less function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedPolynomial.asFunctionOfPolynomial(): (Buffer>) -> NumberedPolynomial = asFunctionOfPolynomialOver(ring) + + /** + * Evaluates value of [this] polynomial on provided [arguments]. + */ + @Suppress("NOTHING_TO_INLINE") + public inline operator fun NumberedPolynomial.invoke(arguments: Buffer): C = substituteFully(ring, arguments) + /** + * Substitutes provided [arguments] into [this] polynomial. + */ + @Suppress("NOTHING_TO_INLINE") + @JvmName("invokePolynomial") + public inline operator fun NumberedPolynomial.invoke(arguments: Buffer>): NumberedPolynomial = substitute(ring, arguments) +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt new file mode 100644 index 000000000..a2986879d --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt @@ -0,0 +1,239 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.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 class NumberedRationalFunction internal constructor( + 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, +) : + RationalFunctionalSpaceOverPolynomialSpace< + 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. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedPolynomial.substitute(argument: Map): NumberedPolynomial = substitute(ring, argument) + /** + * Substitutes provided polynomial [argument] into [this] polynomial. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedPolynomial.substitute(argument: Map>): NumberedPolynomial = substitute(ring, argument) + /** + * Substitutes provided rational function [argument] into [this] polynomial. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedPolynomial.substitute(argument: Map>): NumberedRationalFunction = substitute(ring, argument) + /** + * Substitutes provided constant [argument] into [this] rational function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedRationalFunction.substitute(argument: Map): NumberedRationalFunction = substitute(ring, argument) + /** + * Substitutes provided polynomial [argument] into [this] rational function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedRationalFunction.substitute(argument: Map>): NumberedRationalFunction = substitute(ring, argument) + /** + * Substitutes provided rational function [argument] into [this] rational function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedRationalFunction.substitute(argument: Map>): NumberedRationalFunction = substitute(ring, argument) + /** + * Substitutes provided constant [argument] into [this] polynomial. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedPolynomial.substitute(argument: Buffer): NumberedPolynomial = substitute(ring, argument) + /** + * Substitutes provided polynomial [argument] into [this] polynomial. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedPolynomial.substitute(argument: Buffer>): NumberedPolynomial = substitute(ring, argument) + /** + * Substitutes provided rational function [argument] into [this] polynomial. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedPolynomial.substitute(argument: Buffer>): NumberedRationalFunction = substitute(ring, argument) + /** + * Substitutes provided constant [argument] into [this] rational function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedRationalFunction.substitute(argument: Buffer): NumberedRationalFunction = substitute(ring, argument) + /** + * Substitutes provided polynomial [arguments] into [this] rational function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedRationalFunction.substitute(arguments: Buffer>): NumberedRationalFunction = substitute(ring, arguments) + /** + * Substitutes provided rational function [arguments] into [this] rational function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedRationalFunction.substitute(arguments: Buffer>): NumberedRationalFunction = substitute(ring, arguments) + /** + * Substitutes provided constant [arguments] into [this] polynomial. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedPolynomial.substituteFully(arguments: Buffer): C = substituteFully(ring, arguments) + + /** + * Represent [this] polynomial as a regular context-less function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedPolynomial.asFunction(): (Buffer) -> C = asFunctionOver(ring) + /** + * Represent [this] polynomial as a regular context-less function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedPolynomial.asFunctionOfConstant(): (Buffer) -> C = asFunctionOfConstantOver(ring) + /** + * Represent [this] polynomial as a regular context-less function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedPolynomial.asFunctionOfPolynomial(): (Buffer>) -> NumberedPolynomial = asFunctionOfPolynomialOver(ring) + /** + * Represent [this] polynomial as a regular context-less function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedPolynomial.asFunctionOfRationalFunction(): (Buffer>) -> NumberedRationalFunction = asFunctionOfRationalFunctionOver(ring) + /** + * Represent [this] polynomial as a regular context-less function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedRationalFunction.asFunctionOfPolynomial(): (Buffer>) -> NumberedRationalFunction = asFunctionOfPolynomialOver(ring) + /** + * Represent [this] polynomial as a regular context-less function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun NumberedRationalFunction.asFunctionOfRationalFunction(): (Buffer>) -> NumberedRationalFunction = asFunctionOfRationalFunctionOver(ring) + + /** + * Evaluates value of [this] polynomial on provided [arguments]. + */ + @Suppress("NOTHING_TO_INLINE") + public inline operator fun NumberedPolynomial.invoke(arguments: Buffer): C = substituteFully(ring, arguments) + /** + * Substitutes provided [arguments] into [this] polynomial. + */ + @Suppress("NOTHING_TO_INLINE") + @JvmName("invokePolynomial") + public inline operator fun NumberedPolynomial.invoke(arguments: Buffer>): NumberedPolynomial = substitute(ring, arguments) + /** + * Substitutes provided [arguments] into [this] polynomial. + */ + @Suppress("NOTHING_TO_INLINE") + @JvmName("invokePolynomial") + public inline operator fun NumberedPolynomial.invoke(arguments: Buffer>): NumberedRationalFunction = substitute(ring, arguments) + /** + * Substitutes provided [arguments] into [this] rational function. + */ + @Suppress("NOTHING_TO_INLINE") + @JvmName("invokePolynomial") + public inline operator fun NumberedRationalFunction.invoke(arguments: Buffer>): NumberedRationalFunction = substitute(ring, arguments) + /** + * Substitutes provided [arguments] into [this] rational function. + */ + @Suppress("NOTHING_TO_INLINE") + @JvmName("invokePolynomial") + public inline operator fun NumberedRationalFunction.invoke(arguments: Buffer>): NumberedRationalFunction = substitute(ring, arguments) +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index 01911f980..338ae9935 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -1076,6 +1076,14 @@ public abstract class PolynomialSpaceOfFractions< 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). diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt index 127dd8c7a..649fc48bd 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt @@ -147,12 +147,17 @@ public fun > ListPolynomial.asFunctionOver(ring: A): (C) -> C /** * Represent [this] polynomial as a regular context-less function. */ -public fun > ListPolynomial.asPolynomialFunctionOver(ring: A): (ListPolynomial) -> ListPolynomial = { substitute(ring, it) } +public fun > ListPolynomial.asFunctionOfConstantOver(ring: A): (C) -> C = { substitute(ring, it) } /** * Represent [this] polynomial as a regular context-less function. */ -public fun > ListPolynomial.asFunctionOfRationalFunctionOver(ring: A): (ListPolynomial) -> ListPolynomial = { substitute(ring, it) } +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. @@ -162,12 +167,17 @@ public fun > ListRationalFunction.asFunctionOver(ring: A): (C /** * Represent [this] rational function as a regular context-less function. */ -public fun > ListRationalFunction.asPolynomialFunctionOver(ring: A): (ListPolynomial) -> ListRationalFunction = { substitute(ring, it) } +public fun > ListRationalFunction.asFunctionOfConstantOver(ring: A): (C) -> C = { substitute(ring, it) } /** * Represent [this] rational function as a regular context-less function. */ -public fun > ListRationalFunction.asFunctionOfRationalFunctionOver(ring: A): (ListPolynomial) -> ListRationalFunction = { substitute(ring, it) } +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. @@ -242,27 +252,4 @@ public fun > ListPolynomial.integrate( ): C = ring { val antiderivative = antiderivative(ring) antiderivative.substitute(ring, range.endInclusive) - antiderivative.substitute(ring, range.start) -} - -/** - * Returns algebraic derivative of received rational function. - */ -@UnstableKMathAPI -public fun ListRationalFunction.derivative( - ring: A, -): ListRationalFunction where A : Ring, A : NumericAlgebra = ring.listRationalFunctionSpace { - ListRationalFunction( - numerator.derivative(ring) * denominator - numerator * denominator.derivative(ring), - denominator * denominator - ) -} - -/** - * Returns algebraic derivative of received rational function of specified [order]. The [order] should be non-negative integer. - */ -@UnstableKMathAPI -public tailrec fun ListRationalFunction.nthDerivative( - ring: A, - order: Int, -): ListRationalFunction where A : Ring, A : NumericAlgebra = - if (order == 0) this else derivative(ring).nthDerivative(ring, order - 1) \ No newline at end of file +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt new file mode 100644 index 000000000..05fff3472 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt @@ -0,0 +1,478 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.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. + */ +@Suppress("FunctionName", "NOTHING_TO_INLINE") +@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. + */ +@Suppress("FunctionName", "NOTHING_TO_INLINE") +@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. + */ +@Suppress("FunctionName", "NOTHING_TO_INLINE") +@PublishedApi +internal inline fun NumberedPolynomialAsIs(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. + */ +@Suppress("FunctionName") +public fun NumberedPolynomial(coefs: Map, C>, add: (C, C) -> C) : NumberedPolynomial { + val fixedCoefs = mutableMapOf, C>() + + for (entry in coefs) { + val key = entry.key.cleanUp() + val value = entry.value + fixedCoefs[key] = if (key in fixedCoefs) add(fixedCoefs[key]!!, value) else value + } + + return NumberedPolynomial(fixedCoefs) +} + +/** + * 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. + */ +@Suppress("FunctionName") +public fun NumberedPolynomial(pairs: Collection, C>>, add: (C, C) -> C) : NumberedPolynomial { + val fixedCoefs = mutableMapOf, C>() + + for (entry in pairs) { + val key = entry.first.cleanUp() + val value = entry.second + fixedCoefs[key] = if (key in fixedCoefs) add(fixedCoefs[key]!!, value) else value + } + + return NumberedPolynomial(fixedCoefs) +} + +/** + * 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. + */ +@Suppress("FunctionName") +public fun NumberedPolynomial(vararg pairs: Pair, C>, add: (C, C) -> C) : NumberedPolynomial { + val fixedCoefs = mutableMapOf, C>() + + for (entry in pairs) { + val key = entry.first.cleanUp() + val value = entry.second + fixedCoefs[key] = if (key in fixedCoefs) add(fixedCoefs[key]!!, value) else value + } + + return NumberedPolynomial(fixedCoefs) +} + +// 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. + */ +@Suppress("FunctionName", "NOTHING_TO_INLINE") +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. + */ +@Suppress("FunctionName", "NOTHING_TO_INLINE") +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. + */ +@Suppress("FunctionName", "NOTHING_TO_INLINE") +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. + */ +@Suppress("FunctionName", "NOTHING_TO_INLINE") +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. + */ +@Suppress("FunctionName", "NOTHING_TO_INLINE") +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. + */ +@Suppress("FunctionName", "NOTHING_TO_INLINE") +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. + */ +@Suppress("FunctionName", "NOTHING_TO_INLINE") +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. + */ +@Suppress("FunctionName", "NOTHING_TO_INLINE") +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. + */ +@Suppress("FunctionName", "NOTHING_TO_INLINE") +public inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs) { left: C, right: C -> left + right } + +/** + * Converts [this] constant to [NumberedPolynomial]. + */ +@Suppress("NOTHING_TO_INLINE") +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_1^2 x_3^3 - 6 x_2` can be described as + * ``` + * Int.algebra { + * val numberedPolynomial : NumberedPolynomial = NumberedPolynomial { + * 5 { 1 inPowerOf 2u; 3 inPowerOf 3u } // 5 x_1^2 x_3^3 + + * (-6) { 2 inPowerOf 1u } // (-6) x_2^1 + * } + * } + * ``` + */ +@DslMarker +@UnstableKMathAPI +internal annotation class NumberedPolynomialConstructorDSL + +/** + * Builder of [NumberedPolynomial] signature. It should be used as an implicit context for lambdas that describe term signature. + */ +@UnstableKMathAPI +@NumberedPolynomialConstructorDSL +public class NumberedPolynomialTermSignatureBuilder { + /** + * 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`. + */ + 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 (this > signature.lastIndex) { + signature.addAll(List(this - signature.lastIndex - 1) { 0u }) + signature.add(deg) + } else { + signature[this] += deg + } + } + /** + * Declares power of variable #[this] of degree [deg]. + * + * Declaring another power of the same variable will increase its degree by received degree. + */ + @Suppress("NOTHING_TO_INLINE") + 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. + */ + @Suppress("NOTHING_TO_INLINE") + 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. + */ + @Suppress("NOTHING_TO_INLINE") + 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 +@NumberedPolynomialConstructorDSL +public class NumberedPolynomialBuilder( + /** + * 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 = 0 +) { + /** + * 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> = LinkedHashMap(initialCapacity) + + /** + * 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) { + if (signature in coefficients) coefficients[signature] = add(coefficients[signature]!!, this@with) + else coefficients[signature] = this@with + } + /** + * 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. + */ + @Suppress("NOTHING_TO_INLINE") + public inline infix fun C.with(noinline block: NumberedPolynomialTermSignatureBuilder.() -> 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 operator fun C.invoke(block: NumberedPolynomialTermSignatureBuilder.() -> Unit): Unit = + this with NumberedPolynomialTermSignatureBuilder().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_1^2 x_3^3 - 6 x_2` can be described as + * ``` + * Int.algebra { + * val numberedPolynomial : NumberedPolynomial = NumberedPolynomial { + * 5 { 1 inPowerOf 2u; 3 inPowerOf 3u } // 5 x_1^2 x_3^3 + + * (-6) { 2 inPowerOf 1u } // (-6) x_2^1 + * } + * } + * ``` + */ +@UnstableKMathAPI +@Suppress("FunctionName") +public inline fun > A.NumberedPolynomial(initialCapacity: Int = 0, 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_1^2 x_3^3 - 6 x_2` can be described as + * ``` + * Int.algebra { + * val numberedPolynomial : NumberedPolynomial = NumberedPolynomial { + * 5 { 1 inPowerOf 2u; 3 inPowerOf 3u } // 5 x_1^2 x_3^3 + + * (-6) { 2 inPowerOf 1u } // (-6) x_2^1 + * } + * } + * ``` + */ +@UnstableKMathAPI +@Suppress("FunctionName") +public inline fun > NumberedPolynomialSpace.NumberedPolynomial(initialCapacity: Int, block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder({ 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_1^2 x_3^3 - 6 x_2` can be described as + * ``` + * Int.algebra { + * val numberedPolynomial : NumberedPolynomial = NumberedPolynomial { + * 5 { 1 inPowerOf 2u; 3 inPowerOf 3u } // 5 x_1^2 x_3^3 + + * (-6) { 2 inPowerOf 1u } // (-6) x_2^1 + * } + * } + * ``` + */ +@UnstableKMathAPI +@Suppress("FunctionName") +public inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(initialCapacity: Int, block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder({ 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. + */ +@Suppress("FunctionName") +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. + */ +@Suppress("FunctionName") +public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): NumberedRationalFunction = + NumberedRationalFunction( + NumberedPolynomial(numeratorCoefficients), + NumberedPolynomial(denominatorCoefficients) + ) + +/** + * Constructs [NumberedRationalFunction] with provided [numerator] and unit denominator. + */ +@Suppress("FunctionName") +public fun > A.NumberedRationalFunction(numerator: NumberedPolynomial): NumberedRationalFunction = + NumberedRationalFunction(numerator, NumberedPolynomial(mapOf(emptyList() to one))) +/** + * Constructs [NumberedRationalFunction] with provided [numerator] and unit denominator. + */ +@Suppress("FunctionName") +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. + */ +@Suppress("FunctionName") +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. + */ +@Suppress("FunctionName") +public fun > A.NumberedRationalFunction(numeratorCoefficients: Map, C>): NumberedRationalFunction = + NumberedRationalFunction( + NumberedPolynomial(numeratorCoefficients), + NumberedPolynomialAsIs(mapOf(emptyList() to one)) + ) + +///** +// * Converts [this] coefficient to [NumberedRationalFunction]. +// */ +//context(A) +//public fun > C.asNumberedRationalFunction() : NumberedRationalFunction = +// NumberedRationalFunction( +// NumberedPolynomialAsIs(mapOf(emptyList() to this)), +// NumberedPolynomialAsIs(mapOf(emptyList() to one)) +// ) +///** +// * Converts [this] coefficient 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-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt new file mode 100644 index 000000000..484cd11e3 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt @@ -0,0 +1,515 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.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 fun > A.numberedPolynomialSpace(): NumberedPolynomialSpace = + 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 fun > A.numberedRationalFunctionSpace(): NumberedRationalFunctionSpace = + 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, Double>(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()) + } + if (newDegs !in this) this[newDegs] = newC + else this[newDegs] = this[newDegs]!! + newC + } + } + ) +} + +/** + * Substitutes provided arguments [args] into [this] polynomial. + */ +public fun NumberedPolynomial.substitute(ring: Ring, args: Map): NumberedPolynomial = ring { + NumberedPolynomial( + buildMap, C>(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) + } + if (newDegs !in this) this[newDegs] = newC + else this[newDegs] = this[newDegs]!! + 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 boxing +@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 boxing +@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()) + } + if (newDegs !in this) this[newDegs] = newC + else this[newDegs] = this[newDegs]!! + 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) + } + if (newDegs !in this) this[newDegs] = newC + else this[newDegs] = this[newDegs]!! + 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 boxing +@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 boxing +@JvmName("substituteRationalFunction") +public fun NumberedRationalFunction.substitute(ring: Ring, args: Buffer>) : NumberedRationalFunction = + ring.numberedRationalFunctionSpace { + numerator.substitute(ring, args) / denominator.substitute(ring, args) + } + +/** + * 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 }) { "Fully substituting buffer should cover all variables of the polynomial." } + 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 }) { "Fully substituting buffer should cover all variables of the polynomial." } + 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.size) { + coefficients + .forEach { (degs, c) -> + if (degs.size > 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.size) { + coefficients + .forEach { (degs, c) -> + if (degs.size > 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.size > 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)) { if (it != variable) degs[it] else degs[it] + 1u }, + c / multiplyByDoubling(one, degs[variable]) + ) + } + } + ) +} + +/** + * 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)) { if (it != variable) degs[it] else degs[it] + order }, + degs[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 > 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[it] + filteredVariablesAndOrders.getOrElse(it) { 0u } }, + filteredVariablesAndOrders.entries.fold(c) { acc1, (index, order) -> + degs[index].let { deg -> + (deg downTo deg - order + 1u) + .fold(acc1) { acc2, ord -> acc2 / multiplyByDoubling(one, ord) } + } + } + ) + } + } + ) +} \ No newline at end of file -- 2.34.1 From b5031121ce9ef7ea0c0aae3796da8e736074a083 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 14 Jun 2022 19:31:13 +0300 Subject: [PATCH 095/275] up build tools --- gradle.properties | 2 +- .../kotlin/space/kscience/kmath/geometry/RotationTest.kt | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 9cdd7801c..5202289fa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,4 +12,4 @@ org.gradle.configureondemand=true org.gradle.parallel=true org.gradle.jvmargs=-Xmx4096m -toolsVersion=0.11.6-kotlin-1.7.0 +toolsVersion=0.11.7-kotlin-1.7.0 diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt index ca7226fb6..abe26d398 100644 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt @@ -7,6 +7,7 @@ package space.kscience.kmath.geometry import space.kscience.kmath.complex.Quaternion import space.kscience.kmath.testutils.assertBufferEquals +import kotlin.test.Ignore import kotlin.test.Test import kotlin.test.assertEquals @@ -24,6 +25,7 @@ class RotationTest { } @Test + @Ignore fun rotationConversion() { val q = Quaternion(1.0, 2.0, -3.0, 4.0) -- 2.34.1 From a1267d84ac43ca18d543c44c81514a73f990d50c Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 14 Jun 2022 20:58:13 +0300 Subject: [PATCH 096/275] Fix quaternion rotation tests --- .../kscience/kmath/complex/Quaternion.kt | 2 + .../space/kscience/kmath/nd/Structure2D.kt | 4 ++ .../kscience/kmath/geometry/rotations3D.kt | 60 ++++++++++++------- .../kscience/kmath/geometry/RotationTest.kt | 10 ++-- 4 files changed, 48 insertions(+), 28 deletions(-) diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt index 359b66b20..0305bfc88 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt @@ -117,6 +117,8 @@ public val Quaternion.reciprocal: Quaternion return Quaternion(w / norm2, -x / norm2, -y / norm2, -z / norm2) } +public fun Quaternion.normalized(): Quaternion = with(QuaternionField){ this@normalized / norm(this@normalized) } + /** * A field of [Quaternion]. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index cf8559869..a2fd83474 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 @@ -138,6 +138,10 @@ private class MutableStructure2DWrapper(val structure: MutableStructureND) override fun equals(other: Any?): Boolean = false override fun hashCode(): Int = 0 + + override fun toString(): String { + return StructureND.toString(structure) + } } /** diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/rotations3D.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/rotations3D.kt index 374315610..67c3666ed 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/rotations3D.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/rotations3D.kt @@ -14,7 +14,6 @@ import space.kscience.kmath.linear.linearSpace import space.kscience.kmath.linear.matrix import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.invoke import kotlin.math.pow import kotlin.math.sqrt @@ -33,9 +32,9 @@ public val Quaternion.vector: Vector3D val sint2 = sqrt(1 - w * w) return object : Vector3D { - override val x: Double get() = this@vector.x/sint2 - override val y: Double get() = this@vector.y/sint2 - override val z: Double get() = this@vector.z/sint2 + override val x: Double get() = this@vector.x / sint2 + override val y: Double get() = this@vector.y / sint2 + override val z: Double get() = this@vector.z / sint2 override fun toString(): String = listOf(x, y, z).toString() } } @@ -75,26 +74,43 @@ public fun Quaternion.toRotationMatrix( } /** - * taken from https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2015/01/matrix-to-quat.pdf + * taken from https://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/ */ public fun Quaternion.Companion.fromRotationMatrix(matrix: Matrix): Quaternion { - val t: Double - val q = if (matrix[2, 2] < 0) { - if (matrix[0, 0] > matrix[1, 1]) { - t = 1 + matrix[0, 0] - matrix[1, 1] - matrix[2, 2] - Quaternion(t, matrix[0, 1] + matrix[1, 0], matrix[2, 0] + matrix[0, 2], matrix[1, 2] - matrix[2, 1]) - } else { - t = 1 - matrix[0, 0] + matrix[1, 1] - matrix[2, 2] - Quaternion(matrix[0, 1] + matrix[1, 0], t, matrix[1, 2] + matrix[2, 1], matrix[2, 0] - matrix[0, 2]) - } + require(matrix.colNum == 3 && matrix.rowNum == 3) { "Rotation matrix should be 3x3 but is ${matrix.rowNum}x${matrix.colNum}" } + val trace = matrix[0, 0] + matrix[1, 1] + matrix[2, 2] + + return if (trace > 0) { + val s = sqrt(trace + 1.0) * 2 // S=4*qw + Quaternion( + w = 0.25 * s, + x = (matrix[2, 1] - matrix[1, 2]) / s, + y = (matrix[0, 2] - matrix[2, 0]) / s, + z = (matrix[1, 0] - matrix[0, 1]) / s, + ) + } else if ((matrix[0, 0] > matrix[1, 1]) && (matrix[0, 0] > matrix[2, 2])) { + val s = sqrt(1.0 + matrix[0, 0] - matrix[1, 1] - matrix[2, 2]) * 2 // S=4*qx + Quaternion( + w = (matrix[2, 1] - matrix[1, 2]) / s, + x = 0.25 * s, + y = (matrix[0, 1] + matrix[1, 0]) / s, + z = (matrix[0, 2] + matrix[2, 0]) / s, + ) + } else if (matrix[1, 1] > matrix[2, 2]) { + val s = sqrt(1.0 + matrix[1, 1] - matrix[0, 0] - matrix[2, 2]) * 2 // S=4*qy + Quaternion( + w = (matrix[0, 2] - matrix[2, 0]) / s, + x = (matrix[0, 1] + matrix[1, 0]) / s, + y = 0.25 * s, + z = (matrix[1, 2] + matrix[2, 1]) / s, + ) } else { - if (matrix[0, 0] < -matrix[1, 1]) { - t = 1 - matrix[0, 0] - matrix[1, 1] + matrix[2, 2] - Quaternion(matrix[2, 0] + matrix[0, 2], matrix[1, 2] + matrix[2, 1], t, matrix[0, 1] - matrix[1, 0]) - } else { - t = 1 + matrix[0, 0] + matrix[1, 1] + matrix[2, 2] - Quaternion(matrix[1, 2] - matrix[2, 1], matrix[2, 0] - matrix[0, 2], matrix[0, 1] - matrix[1, 0], t) - } + val s = sqrt(1.0 + matrix[2, 2] - matrix[0, 0] - matrix[1, 1]) * 2 // S=4*qz + Quaternion( + w = (matrix[1, 0] - matrix[0, 1]) / s, + x = (matrix[0, 2] + matrix[2, 0]) / s, + y = (matrix[1, 2] + matrix[2, 1]) / s, + z = 0.25 * s, + ) } - return QuaternionField.invoke { q * (0.5 / sqrt(t)) } } \ No newline at end of file diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt index abe26d398..89b69d0f2 100644 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt @@ -6,17 +6,16 @@ package space.kscience.kmath.geometry import space.kscience.kmath.complex.Quaternion +import space.kscience.kmath.complex.normalized import space.kscience.kmath.testutils.assertBufferEquals -import kotlin.test.Ignore import kotlin.test.Test -import kotlin.test.assertEquals class RotationTest { @Test fun rotations() = with(Euclidean3DSpace) { val vector = Vector3D(1.0, 1.0, 1.0) - val q = Quaternion(1.0, 2.0, -3.0, 4.0) + val q = Quaternion(1.0, 2.0, -3.0, 4.0).normalized() val rotatedByQ = rotate(vector, q) val matrix = q.toRotationMatrix() val rotatedByM = rotate(vector,matrix) @@ -25,13 +24,12 @@ class RotationTest { } @Test - @Ignore fun rotationConversion() { - val q = Quaternion(1.0, 2.0, -3.0, 4.0) + val q = Quaternion(1.0, 2.0, -3.0, 4.0).normalized() val matrix = q.toRotationMatrix() - assertEquals(q, Quaternion.fromRotationMatrix(matrix)) + assertBufferEquals(q, Quaternion.fromRotationMatrix(matrix)) } } \ No newline at end of file -- 2.34.1 From b5a94923b574bb840214fde3e1af1875c64777ef Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Fri, 17 Jun 2022 01:53:40 +0300 Subject: [PATCH 097/275] Fixed problems with JVM names. Exposed internal NumberedPolynomial constructor with opt-in condition. Added and upgraded tests. Fixed small bugs (mistakes). Upgraded arithmetic operations a bit. --- .../kmath/functions/ListPolynomial.kt | 60 +- .../kmath/functions/NumberedPolynomial.kt | 60 +- .../functions/NumberedRationalFunction.kt | 12 +- .../space/kscience/kmath/functions/misc.kt | 21 +- .../kmath/functions/numberedConstructors.kt | 79 +- .../kscience/kmath/functions/numberedUtil.kt | 2 +- .../kmath/functions/ListPolynomialTest.kt | 94 +- .../functions/NumberedConstructorsTest.kt | 111 ++ .../kmath/functions/NumberedPolynomialTest.kt | 1368 +++++++++++++++++ .../kscience/kmath/test/misc/IntModulo.kt | 6 +- 10 files changed, 1714 insertions(+), 99 deletions(-) create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt index 42e3f7301..b3f1eb8f7 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt @@ -100,14 +100,17 @@ public open class ListPolynomialSpace>( * The operation is equivalent to sum of [other] copies of [this]. */ public override operator fun ListPolynomial.times(other: Int): ListPolynomial = - if (other == 0) zero - else ListPolynomial( - coefficients - .toMutableList() - .apply { - for (deg in indices) this[deg] = this[deg] * other - } - ) + when (other) { + 0 -> zero + 1 -> this + else -> ListPolynomial( + coefficients + .toMutableList() + .apply { + for (deg in indices) this[deg] = this[deg] * other + } + ) + } /** * Returns sum of the integer represented as a polynomial and the polynomial. @@ -133,34 +136,39 @@ public open class ListPolynomialSpace>( * The operation is equivalent to subtraction [this] copies of unit polynomial from [other]. */ public override operator fun Int.minus(other: ListPolynomial): ListPolynomial = - if (this == 0) other - else - ListPolynomial( - other.coefficients - .toMutableList() - .apply { - forEachIndexed { index, c -> if (index != 0) this[index] = -c } + 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) + 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 = - if (this == 0) zero - else ListPolynomial( - other.coefficients - .toMutableList() - .apply { - for (deg in indices) this[deg] = this@times * this[deg] - } - ) + when (this) { + 0 -> zero + 1 -> other + else -> ListPolynomial( + other.coefficients + .toMutableList() + .apply { + for (deg in indices) this[deg] = this@times * this[deg] + } + ) + } /** * Converts the integer [value] to polynomial. @@ -192,7 +200,7 @@ public open class ListPolynomialSpace>( else ListPolynomial( toMutableList() .apply { - forEachIndexed { index, c -> if (index != 0) this[index] = -c } + (1 .. lastIndex).forEach { this[it] = -this[it] } val result = if (size == 0) this@minus else this@minus - get(0) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index 9304e66da..02a3af683 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -98,14 +98,17 @@ public class NumberedPolynomialSpace>( * The operation is equivalent to sum of [other] copies of [this]. */ public override operator fun NumberedPolynomial.times(other: Int): NumberedPolynomial = - if (other == 0) zero - else NumberedPolynomialAsIs( - coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this[degs]!! * other - } - ) + when (other) { + 0 -> zero + 1 -> this + else -> NumberedPolynomialAsIs( + coefficients + .toMutableMap() + .apply { + for (degs in keys) this[degs] = this[degs]!! * other + } + ) + } /** * Returns sum of the integer represented as a polynomial and the polynomial. @@ -130,16 +133,20 @@ public class NumberedPolynomialSpace>( * The operation is equivalent to subtraction [this] copies of unit polynomial from [other]. */ public override operator fun Int.minus(other: NumberedPolynomial): NumberedPolynomial = - if (this == 0) other - else - NumberedPolynomialAsIs( - other.coefficients - .toMutableMap() - .apply { + NumberedPolynomialAsIs( + other.coefficients + .toMutableMap() + .apply { + if (this@minus == 0) { + forEach { (key, value) -> this[key] = -value } + } else { + forEach { (key, value) -> if (key.isNotEmpty()) this[key] = -value } + val degs = emptyList() this[degs] = this@minus - getOrElse(degs) { constantZero } } + } ) /** * Returns product of the integer represented as a polynomial and the polynomial. @@ -147,14 +154,17 @@ public class NumberedPolynomialSpace>( * The operation is equivalent to sum of [this] copies of [other]. */ public override operator fun Int.times(other: NumberedPolynomial): NumberedPolynomial = - if (this == 0) zero - else NumberedPolynomialAsIs( - other.coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this@times * this[degs]!! - } - ) + when (this) { + 0 -> zero + 1 -> other + else -> NumberedPolynomialAsIs( + other.coefficients + .toMutableMap() + .apply { + for (degs in keys) this[degs] = this@times * this[degs]!! + } + ) + } /** * Converts the integer [value] to polynomial. @@ -185,7 +195,7 @@ public class NumberedPolynomialSpace>( else NumberedPolynomialAsIs( toMutableMap() .apply { - forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } + forEach { (degs, c) -> if (degs.isNotEmpty()) this[degs] = -c } val degs = emptyList() @@ -266,7 +276,7 @@ public class NumberedPolynomialSpace>( override operator fun NumberedPolynomial.plus(other: NumberedPolynomial): NumberedPolynomial = NumberedPolynomialAsIs( buildMap(coefficients.size + other.coefficients.size) { - other.coefficients.mapValuesTo(this) { it.value } + coefficients.mapValuesTo(this) { it.value } other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value } } ) @@ -276,7 +286,7 @@ public class NumberedPolynomialSpace>( override operator fun NumberedPolynomial.minus(other: NumberedPolynomial): NumberedPolynomial = NumberedPolynomialAsIs( buildMap(coefficients.size + other.coefficients.size) { - other.coefficients.mapValuesTo(this) { it.value } + coefficients.mapValuesTo(this) { it.value } other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value } } ) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt index a2986879d..92f507735 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt @@ -119,11 +119,13 @@ public class NumberedRationalFunctionSpace> ( * Substitutes provided polynomial [argument] into [this] polynomial. */ @Suppress("NOTHING_TO_INLINE") + @JvmName("substitutePolynomial") public inline fun NumberedPolynomial.substitute(argument: Map>): NumberedPolynomial = substitute(ring, argument) /** * Substitutes provided rational function [argument] into [this] polynomial. */ @Suppress("NOTHING_TO_INLINE") + @JvmName("substituteRationalFunction") public inline fun NumberedPolynomial.substitute(argument: Map>): NumberedRationalFunction = substitute(ring, argument) /** * Substitutes provided constant [argument] into [this] rational function. @@ -134,11 +136,13 @@ public class NumberedRationalFunctionSpace> ( * Substitutes provided polynomial [argument] into [this] rational function. */ @Suppress("NOTHING_TO_INLINE") + @JvmName("substitutePolynomial") public inline fun NumberedRationalFunction.substitute(argument: Map>): NumberedRationalFunction = substitute(ring, argument) /** * Substitutes provided rational function [argument] into [this] rational function. */ @Suppress("NOTHING_TO_INLINE") + @JvmName("substituteRationalFunction") public inline fun NumberedRationalFunction.substitute(argument: Map>): NumberedRationalFunction = substitute(ring, argument) /** * Substitutes provided constant [argument] into [this] polynomial. @@ -149,11 +153,13 @@ public class NumberedRationalFunctionSpace> ( * Substitutes provided polynomial [argument] into [this] polynomial. */ @Suppress("NOTHING_TO_INLINE") + @JvmName("substitutePolynomial") public inline fun NumberedPolynomial.substitute(argument: Buffer>): NumberedPolynomial = substitute(ring, argument) /** * Substitutes provided rational function [argument] into [this] polynomial. */ @Suppress("NOTHING_TO_INLINE") + @JvmName("substituteRationalFunction") public inline fun NumberedPolynomial.substitute(argument: Buffer>): NumberedRationalFunction = substitute(ring, argument) /** * Substitutes provided constant [argument] into [this] rational function. @@ -164,11 +170,13 @@ public class NumberedRationalFunctionSpace> ( * Substitutes provided polynomial [arguments] into [this] rational function. */ @Suppress("NOTHING_TO_INLINE") + @JvmName("substitutePolynomial") public inline fun NumberedRationalFunction.substitute(arguments: Buffer>): NumberedRationalFunction = substitute(ring, arguments) /** * Substitutes provided rational function [arguments] into [this] rational function. */ @Suppress("NOTHING_TO_INLINE") + @JvmName("substituteRationalFunction") public inline fun NumberedRationalFunction.substitute(arguments: Buffer>): NumberedRationalFunction = substitute(ring, arguments) /** * Substitutes provided constant [arguments] into [this] polynomial. @@ -222,7 +230,7 @@ public class NumberedRationalFunctionSpace> ( * Substitutes provided [arguments] into [this] polynomial. */ @Suppress("NOTHING_TO_INLINE") - @JvmName("invokePolynomial") + @JvmName("invokeRationalFunction") public inline operator fun NumberedPolynomial.invoke(arguments: Buffer>): NumberedRationalFunction = substitute(ring, arguments) /** * Substitutes provided [arguments] into [this] rational function. @@ -234,6 +242,6 @@ public class NumberedRationalFunctionSpace> ( * Substitutes provided [arguments] into [this] rational function. */ @Suppress("NOTHING_TO_INLINE") - @JvmName("invokePolynomial") + @JvmName("invokeRationalFunction") public inline operator fun NumberedRationalFunction.invoke(arguments: Buffer>): NumberedRationalFunction = substitute(ring, arguments) } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt index 8b6fac39e..7d6fc84fa 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt @@ -6,8 +6,27 @@ package space.kscience.kmath.functions +/** + * Marks operations that are going to be optimized reimplementations by reducing number of boxings but currently is + * under development and is not stable (or even ready to use). + */ @RequiresOptIn( message = "It's copy of operation with optimized boxing. It's currently unstable.", level = RequiresOptIn.Level.ERROR ) -internal annotation class UnstablePolynomialBoxingOptimization \ No newline at end of file +internal annotation class UnstablePolynomialBoxingOptimization + +/** + * 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.WARNING +) +internal annotation class DelicatePolynomialAPI \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt index 05fff3472..37d5d7fb6 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt @@ -37,6 +37,38 @@ internal inline fun NumberedPolynomialAsIs(pairs: Collection @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.** + */ +@Suppress("FunctionName", "NOTHING_TO_INLINE") +@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.** + */ +@Suppress("FunctionName", "NOTHING_TO_INLINE") +@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.** + */ +@Suppress("FunctionName", "NOTHING_TO_INLINE") +@DelicatePolynomialAPI +public inline fun NumberedPolynomialWithoutCheck(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(pairs.toMap()) + /** * Constructs [NumberedPolynomial] with provided coefficients map [coefs]. * @@ -245,11 +277,12 @@ public class NumberedPolynomialTermSignatureBuilder { * Declaring another power of the same variable will increase its degree by received degree. */ public infix fun Int.inPowerOf(deg: UInt) { - if (this > signature.lastIndex) { - signature.addAll(List(this - signature.lastIndex - 1) { 0u }) + val index = this - 1 + if (index > signature.lastIndex) { + signature.addAll(List(index - signature.lastIndex - 1) { 0u }) signature.add(deg) } else { - signature[this] += deg + signature[index] += deg } } /** @@ -334,22 +367,26 @@ public class NumberedPolynomialBuilder( // 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_1^2 x_3^3 - 6 x_2` can be described as - * ``` - * Int.algebra { - * val numberedPolynomial : NumberedPolynomial = NumberedPolynomial { - * 5 { 1 inPowerOf 2u; 3 inPowerOf 3u } // 5 x_1^2 x_3^3 + - * (-6) { 2 inPowerOf 1u } // (-6) x_2^1 - * } - * } - * ``` - */ -@UnstableKMathAPI -@Suppress("FunctionName") -public inline fun > A.NumberedPolynomial(initialCapacity: Int = 0, block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder(::add, initialCapacity).apply(block).build() +///** +// * Creates [NumberedPolynomial] with lambda [block] in context of [this] ring of constants. +// * +// * For example, polynomial `5 x_1^2 x_3^3 - 6 x_2` can be described as +// * ``` +// * Int.algebra { +// * val numberedPolynomial : NumberedPolynomial = NumberedPolynomial { +// * 5 { 1 inPowerOf 2u; 3 inPowerOf 3u } // 5 x_1^2 x_3^3 + +// * (-6) { 2 inPowerOf 1u } // (-6) x_2^1 +// * } +// * } +// * ``` +// */ +// 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 +//@Suppress("FunctionName") +//public inline fun > A.NumberedPolynomial(initialCapacity: Int = 0, block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder(::add, initialCapacity).apply(block).build() /** * Creates [NumberedPolynomial] with lambda [block] in context of [this] ring of [NumberedPolynomial]s. * @@ -365,7 +402,7 @@ public inline fun > A.NumberedPolynomial(initialCapacity: Int = 0, */ @UnstableKMathAPI @Suppress("FunctionName") -public inline fun > NumberedPolynomialSpace.NumberedPolynomial(initialCapacity: Int, block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build() +public inline fun > NumberedPolynomialSpace.NumberedPolynomial(initialCapacity: Int = 0, block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build() /** * Creates [NumberedPolynomial] with lambda [block] in context of [this] field of [NumberedRationalFunction]s. * @@ -381,7 +418,7 @@ public inline fun > NumberedPolynomialSpace.NumberedPolynomi */ @UnstableKMathAPI @Suppress("FunctionName") -public inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(initialCapacity: Int, block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build() +public inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(initialCapacity: Int = 0, block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build() // Waiting for context receivers :( FIXME: Replace with context receivers when they will be available diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt index 484cd11e3..fca9a8ab8 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt @@ -86,7 +86,7 @@ public fun NumberedPolynomial.substitute(ring: Ring, args: Map /** * Substitutes provided arguments [args] into [this] polynomial. - */ // TODO: To optimize boxing + */ // TODO: To optimize boxing @JvmName("substitutePolynomial") public fun NumberedPolynomial.substitute(ring: Ring, args: Map>) : NumberedPolynomial = ring.numberedPolynomialSpace { diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt index c9950fac5..c4a7cc564 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.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("LocalVariableName") + package space.kscience.kmath.functions import space.kscience.kmath.test.misc.* @@ -28,25 +30,32 @@ class ListPolynomialTest { ListPolynomial(Rational(-2)) + 2, "test 3" ) - assertEquals( - ListPolynomial(), - ListPolynomial() + 0, + 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 5" + "test 6" ) assertEquals( ListPolynomial(Rational(-1)), ListPolynomial(Rational(-2)) + 1, - "test 6" + "test 7" ) assertEquals( ListPolynomial(Rational(2)), ListPolynomial() + 2, - "test 7" + "test 8" ) } } @@ -68,25 +77,32 @@ class ListPolynomialTest { ListPolynomial(Rational(2)) - 2, "test 3" ) - assertEquals( - ListPolynomial(), - ListPolynomial() - 0, + 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 5" + "test 6" ) assertEquals( ListPolynomial(Rational(1)), ListPolynomial(Rational(2)) - 1, - "test 6" + "test 7" ) assertEquals( ListPolynomial(Rational(-2)), ListPolynomial() - 2, - "test 7" + "test 8" ) } } @@ -103,6 +119,17 @@ class ListPolynomialTest { 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 @@ -123,25 +150,32 @@ class ListPolynomialTest { 2 + ListPolynomial(Rational(-2)), "test 3" ) - assertEquals( - ListPolynomial(), - 0 + ListPolynomial(), + 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 5" + "test 6" ) assertEquals( ListPolynomial(Rational(-1)), 1 + ListPolynomial(Rational(-2)), - "test 6" + "test 7" ) assertEquals( ListPolynomial(Rational(2)), 2 + ListPolynomial(), - "test 7" + "test 8" ) } } @@ -163,25 +197,30 @@ class ListPolynomialTest { -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 4" + "test 5" ) assertEquals( ListPolynomial(Rational(1), Rational(0), Rational(0), Rational(0)), -1 - ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), - "test 5" + "test 6" ) assertEquals( ListPolynomial(Rational(1)), -1 - ListPolynomial(Rational(-2)), - "test 6" + "test 7" ) assertEquals( ListPolynomial(Rational(-2)), -2 - ListPolynomial(), - "test 7" + "test 8" ) } } @@ -198,6 +237,17 @@ class ListPolynomialTest { 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 diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt new file mode 100644 index 000000000..14493aaae --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt @@ -0,0 +1,111 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.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 testBuilder() { + assertEquals( + NumberedPolynomialAsIs( + listOf(2u, 0u, 3u) to 5, + listOf(0u, 1u) to -6, + ), + Int.algebra.numberedPolynomialSpace { + NumberedPolynomial { + 5 { 1 inPowerOf 2u; 3 inPowerOf 3u } + (-6) { 2 inPowerOf 1u } + } + }, + "test 1" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf() to -1, + ), + Int.algebra.numberedPolynomialSpace { + NumberedPolynomial { + 5 { } + (-6) { } + } + }, + "test 2" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(2u) to -1, + ), + Int.algebra.numberedPolynomialSpace { + NumberedPolynomial { + 5 { 1 inPowerOf 1u; 1 inPowerOf 1u } + (-6) { 1 inPowerOf 2u } + } + }, + "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-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt new file mode 100644 index 000000000..537e3b85d --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt @@ -0,0 +1,1368 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +@file:Suppress("LocalVariableName") + +package space.kscience.kmath.functions + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.test.misc.* +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertSame + + +@UnstableKMathAPI +class NumberedPolynomialTest { + @Test + fun test_Polynomial_Int_plus() { + RationalField.numberedPolynomialSpace { + assertEquals( + NumberedPolynomial { + Rational(-22, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + NumberedPolynomial { + Rational(5, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } + -3, + "test 1" + ) + assertEquals( + NumberedPolynomial { + Rational(-3, 1) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + NumberedPolynomial { + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } + -3, + "test 2" + ) + assertEquals( + NumberedPolynomial { + Rational(0, 1) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + NumberedPolynomial { + Rational(27, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } + -3, + "test 3" + ) + assertEquals( + NumberedPolynomial { + Rational(0, 1) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + NumberedPolynomial { + Rational(27, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } + -3, + "test 4" + ) + val polynomial_5 = NumberedPolynomial { + Rational(-22, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } + assertSame( + polynomial_5, + polynomial_5 + 0, + "test 5" + ) + val polynomial_6 = NumberedPolynomial { + Rational(0, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } + assertSame( + polynomial_6, + polynomial_6 + 0, + "test 6" + ) + val polynomial_7 = NumberedPolynomial { + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } + assertSame( + polynomial_7, + polynomial_7 + 0, + "test 7" + ) + } + } + @Test + fun test_Polynomial_Int_minus() { + RationalField.numberedPolynomialSpace { + assertEquals( + NumberedPolynomial { + Rational(-22, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + NumberedPolynomial { + Rational(5, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } - 3, + "test 1" + ) + assertEquals( + NumberedPolynomial { + Rational(-3, 1) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + NumberedPolynomial { + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } - 3, + "test 2" + ) + assertEquals( + NumberedPolynomial { + Rational(0, 1) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + NumberedPolynomial { + Rational(27, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } - 3, + "test 3" + ) + assertEquals( + NumberedPolynomial { + Rational(0, 1) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + NumberedPolynomial { + Rational(27, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } - 3, + "test 4" + ) + val polynomial_5 = NumberedPolynomial { + Rational(-22, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } + assertSame( + polynomial_5, + polynomial_5 - 0, + "test 5" + ) + val polynomial_6 = NumberedPolynomial { + Rational(0, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } + assertSame( + polynomial_6, + polynomial_6 - 0, + "test 6" + ) + val polynomial_7 = NumberedPolynomial { + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } + assertSame( + polynomial_7, + polynomial_7 - 0, + "test 7" + ) + } + } + @Test + fun test_Polynomial_Int_times() { + IntModuloRing(35).numberedPolynomialSpace { + assertEquals( + NumberedPolynomial { + m(34) with {} + m(2) with { 1 pow 3u } + m(1) with { 2 pow 1u } + m(20) with { 1 pow 1u } + m(2) with { 3 pow 2u } + }, + NumberedPolynomial { + m(22) with {} + m(26) with { 1 pow 3u } + m(13) with { 2 pow 1u } + m(15) with { 1 pow 1u } + m(26) with { 3 pow 2u } + } * 27, + "test 1" + ) + assertEquals( + NumberedPolynomial { + m(0) with {} + m(0) with { 1 pow 3u } + m(0) with { 2 pow 1u } + m(0) with { 1 pow 1u } + m(0) with { 3 pow 2u } + }, + NumberedPolynomial { + m(7) with {} + m(0) with { 1 pow 3u } + m(49) with { 2 pow 1u } + m(21) with { 1 pow 1u } + m(14) with { 3 pow 2u } + } * 15, + "test 2" + ) + val polynomial = NumberedPolynomial { + m(22) with {} + m(26) with { 1 pow 3u } + m(13) with { 2 pow 1u } + m(15) with { 1 pow 1u } + m(26) with { 3 pow 2u } + } + assertSame( + zero, + polynomial * 0, + "test 3" + ) + assertSame( + polynomial, + polynomial * 1, + "test 4" + ) + } + } + @Test + fun test_Int_Polynomial_plus() { + RationalField.numberedPolynomialSpace { + assertEquals( + NumberedPolynomial { + Rational(-22, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + -3 + NumberedPolynomial { + Rational(5, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + "test 1" + ) + assertEquals( + NumberedPolynomial { + Rational(-3, 1) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + -3 + NumberedPolynomial { + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + "test 2" + ) + assertEquals( + NumberedPolynomial { + Rational(0, 1) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + -3 + NumberedPolynomial { + Rational(27, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + "test 3" + ) + assertEquals( + NumberedPolynomial { + Rational(0, 1) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + -3 + NumberedPolynomial { + Rational(27, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + "test 4" + ) + val polynomial_5 = NumberedPolynomial { + Rational(-22, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } + assertSame( + polynomial_5, + 0 + polynomial_5, + "test 5" + ) + val polynomial_6 = NumberedPolynomial { + Rational(0, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } + assertSame( + polynomial_6, + 0 + polynomial_6, + "test 6" + ) + val polynomial_7 = NumberedPolynomial { + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } + assertSame( + polynomial_7, + 0 + polynomial_7, + "test 7" + ) + } + } + @Test + fun test_Int_Polynomial_minus() { + RationalField.numberedPolynomialSpace { + assertEquals( + NumberedPolynomial { + Rational(22, 9) with {} + Rational(8, 9) with { 1 pow 3u } + Rational(8, 7) with { 2 pow 4u } + }, + 3 - NumberedPolynomial { + Rational(5, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + "test 1" + ) + assertEquals( + NumberedPolynomial { + Rational(3, 1) with {} + Rational(8, 9) with { 1 pow 3u } + Rational(8, 7) with { 2 pow 4u } + }, + 3 - NumberedPolynomial { + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + "test 2" + ) + assertEquals( + NumberedPolynomial { + Rational(0, 1) with {} + Rational(8, 9) with { 1 pow 3u } + Rational(8, 7) with { 2 pow 4u } + }, + 3 - NumberedPolynomial { + Rational(27, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + "test 3" + ) + assertEquals( + NumberedPolynomial { + Rational(0, 1) with {} + Rational(8, 9) with { 1 pow 3u } + Rational(8, 7) with { 2 pow 4u } + }, + 3 - NumberedPolynomial { + Rational(27, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + "test 4" + ) + assertEquals( + NumberedPolynomial { + Rational(22, 9) with {} + Rational(8, 9) with { 1 pow 3u } + Rational(8, 7) with { 2 pow 4u } + }, + 0 - NumberedPolynomial { + Rational(-22, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + "test 5" + ) + assertEquals( + NumberedPolynomial { + Rational(0, 9) with {} + Rational(8, 9) with { 1 pow 3u } + Rational(8, 7) with { 2 pow 4u } + }, + 0 - NumberedPolynomial { + Rational(0, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + "test 6" + ) + assertEquals( + NumberedPolynomial { + Rational(8, 9) with { 1 pow 3u } + Rational(8, 7) with { 2 pow 4u } + }, + 0 - NumberedPolynomial { + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + "test 7" + ) + } + } + @Test + fun test_Int_Polynomial_times() { + IntModuloRing(35).numberedPolynomialSpace { + assertEquals( + NumberedPolynomial { + m(34) with {} + m(2) with { 1 pow 3u } + m(1) with { 2 pow 1u } + m(20) with { 1 pow 1u } + m(2) with { 3 pow 2u } + }, + 27 * NumberedPolynomial { + m(22) with {} + m(26) with { 1 pow 3u } + m(13) with { 2 pow 1u } + m(15) with { 1 pow 1u } + m(26) with { 3 pow 2u } + }, + "test 1" + ) + assertEquals( + NumberedPolynomial { + m(0) with {} + m(0) with { 1 pow 3u } + m(0) with { 2 pow 1u } + m(0) with { 1 pow 1u } + m(0) with { 3 pow 2u } + }, + 15 * NumberedPolynomial { + m(7) with {} + m(0) with { 1 pow 3u } + m(49) with { 2 pow 1u } + m(21) with { 1 pow 1u } + m(14) with { 3 pow 2u } + }, + "test 2" + ) + val polynomial = NumberedPolynomial { + m(22) with {} + m(26) with { 1 pow 3u } + m(13) with { 2 pow 1u } + m(15) with { 1 pow 1u } + m(26) with { 3 pow 2u } + } + assertSame( + zero, + 0 * polynomial, + "test 3" + ) + assertSame( + polynomial, + 1 * polynomial, + "test 4" + ) + } + } + @Test + fun test_Polynomial_Constant_plus() { + RationalField.numberedPolynomialSpace { + assertEquals( + NumberedPolynomial { + Rational(-22, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + NumberedPolynomial { + Rational(5, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } + Rational(-3), + "test 1" + ) + assertEquals( + NumberedPolynomial { + Rational(-3, 1) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + NumberedPolynomial { + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } + Rational(-3), + "test 2" + ) + assertEquals( + NumberedPolynomial { + Rational(0, 1) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + NumberedPolynomial { + Rational(27, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } + Rational(-3), + "test 3" + ) + assertEquals( + NumberedPolynomial { + Rational(0, 1) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + NumberedPolynomial { + Rational(27, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } + Rational(-3), + "test 4" + ) + assertEquals( + NumberedPolynomial { + Rational(-22, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + NumberedPolynomial { + Rational(-22, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } + Rational(0), + "test 5" + ) + assertEquals( + NumberedPolynomial { + Rational(0, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + NumberedPolynomial { + Rational(0, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } + Rational(0), + "test 6" + ) + assertEquals( + NumberedPolynomial { + Rational(0) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + NumberedPolynomial { + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } + Rational(0), + "test 7" + ) + } + } + @Test + fun test_Polynomial_Constant_minus() { + RationalField.numberedPolynomialSpace { + assertEquals( + NumberedPolynomial { + Rational(-22, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + NumberedPolynomial { + Rational(5, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } - Rational(3), + "test 1" + ) + assertEquals( + NumberedPolynomial { + Rational(-3, 1) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + NumberedPolynomial { + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } - Rational(3), + "test 2" + ) + assertEquals( + NumberedPolynomial { + Rational(0, 1) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + NumberedPolynomial { + Rational(27, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } - Rational(3), + "test 3" + ) + assertEquals( + NumberedPolynomial { + Rational(0, 1) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + NumberedPolynomial { + Rational(27, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } - Rational(3), + "test 4" + ) + assertEquals( + NumberedPolynomial { + Rational(-22, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + NumberedPolynomial { + Rational(-22, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } - Rational(0), + "test 5" + ) + assertEquals( + NumberedPolynomial { + Rational(0, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + NumberedPolynomial { + Rational(0, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } - Rational(0), + "test 6" + ) + assertEquals( + NumberedPolynomial { + Rational(0) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + NumberedPolynomial { + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + } - Rational(0), + "test 7" + ) + } + } + @Test + fun test_Polynomial_Constant_times() { + IntModuloRing(35).numberedPolynomialSpace { + assertEquals( + NumberedPolynomial { + m(34) with {} + m(2) with { 1 pow 3u } + m(1) with { 2 pow 1u } + m(20) with { 1 pow 1u } + m(2) with { 3 pow 2u } + }, + NumberedPolynomial { + m(22) with {} + m(26) with { 1 pow 3u } + m(13) with { 2 pow 1u } + m(15) with { 1 pow 1u } + m(26) with { 3 pow 2u } + } * m(27), + "test 1" + ) + assertEquals( + NumberedPolynomial { + m(0) with {} + m(0) with { 1 pow 3u } + m(0) with { 2 pow 1u } + m(0) with { 1 pow 1u } + m(0) with { 3 pow 2u } + }, + NumberedPolynomial { + m(7) with {} + m(0) with { 1 pow 3u } + m(49) with { 2 pow 1u } + m(21) with { 1 pow 1u } + m(14) with { 3 pow 2u } + } * m(15), + "test 2" + ) + assertEquals( + NumberedPolynomial { + m(0) with {} + m(0) with { 1 pow 3u } + m(0) with { 2 pow 1u } + m(0) with { 1 pow 1u } + m(0) with { 3 pow 2u } + }, + NumberedPolynomial { + m(22) with {} + m(26) with { 1 pow 3u } + m(13) with { 2 pow 1u } + m(15) with { 1 pow 1u } + m(26) with { 3 pow 2u } + } * m(0), + "test 3" + ) + assertEquals( + NumberedPolynomial { + m(22) with {} + m(26) with { 1 pow 3u } + m(13) with { 2 pow 1u } + m(15) with { 1 pow 1u } + m(26) with { 3 pow 2u } + }, + NumberedPolynomial { + m(22) with {} + m(26) with { 1 pow 3u } + m(13) with { 2 pow 1u } + m(15) with { 1 pow 1u } + m(26) with { 3 pow 2u } + } * m(1), + "test 4" + ) + } + } + @Test + fun test_Constant_Polynomial_plus() { + RationalField.numberedPolynomialSpace { + assertEquals( + NumberedPolynomial { + Rational(-22, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + Rational(-3) + NumberedPolynomial { + Rational(5, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + "test 1" + ) + assertEquals( + NumberedPolynomial { + Rational(-3, 1) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + Rational(-3) + NumberedPolynomial { + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + "test 2" + ) + assertEquals( + NumberedPolynomial { + Rational(0, 1) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + Rational(-3) + NumberedPolynomial { + Rational(27, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + "test 3" + ) + assertEquals( + NumberedPolynomial { + Rational(0, 1) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + Rational(-3) + NumberedPolynomial { + Rational(27, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + "test 4" + ) + assertEquals( + NumberedPolynomial { + Rational(-22, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + Rational(0) + NumberedPolynomial { + Rational(-22, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + "test 5" + ) + assertEquals( + NumberedPolynomial { + Rational(0, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + Rational(0) + NumberedPolynomial { + Rational(0, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + "test 6" + ) + assertEquals( + NumberedPolynomial { + Rational(0) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + Rational(0) + NumberedPolynomial { + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + "test 7" + ) + } + } + @Test + fun test_Constant_Polynomial_minus() { + RationalField.numberedPolynomialSpace { + assertEquals( + NumberedPolynomial { + Rational(22, 9) with {} + Rational(8, 9) with { 1 pow 3u } + Rational(8, 7) with { 2 pow 4u } + }, + Rational(3) - NumberedPolynomial { + Rational(5, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + "test 1" + ) + assertEquals( + NumberedPolynomial { + Rational(3, 1) with {} + Rational(8, 9) with { 1 pow 3u } + Rational(8, 7) with { 2 pow 4u } + }, + Rational(3) - NumberedPolynomial { + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + "test 2" + ) + assertEquals( + NumberedPolynomial { + Rational(0, 1) with {} + Rational(8, 9) with { 1 pow 3u } + Rational(8, 7) with { 2 pow 4u } + }, + Rational(3) - NumberedPolynomial { + Rational(27, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + "test 3" + ) + assertEquals( + NumberedPolynomial { + Rational(0, 1) with {} + Rational(8, 9) with { 1 pow 3u } + Rational(8, 7) with { 2 pow 4u } + }, + Rational(3) - NumberedPolynomial { + Rational(27, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + "test 4" + ) + assertEquals( + NumberedPolynomial { + Rational(22, 9) with {} + Rational(8, 9) with { 1 pow 3u } + Rational(8, 7) with { 2 pow 4u } + }, + Rational(0) - NumberedPolynomial { + Rational(-22, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + "test 5" + ) + assertEquals( + NumberedPolynomial { + Rational(0, 9) with {} + Rational(8, 9) with { 1 pow 3u } + Rational(8, 7) with { 2 pow 4u } + }, + Rational(0) - NumberedPolynomial { + Rational(0, 9) with {} + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + "test 6" + ) + assertEquals( + NumberedPolynomial { + Rational(0) with {} + Rational(8, 9) with { 1 pow 3u } + Rational(8, 7) with { 2 pow 4u } + }, + Rational(0) - NumberedPolynomial { + Rational(-8, 9) with { 1 pow 3u } + Rational(-8, 7) with { 2 pow 4u } + }, + "test 7" + ) + } + } + @Test + fun test_Constant_Polynomial_times() { + IntModuloRing(35).numberedPolynomialSpace { + assertEquals( + NumberedPolynomial { + m(34) with {} + m(2) with { 1 pow 3u } + m(1) with { 2 pow 1u } + m(20) with { 1 pow 1u } + m(2) with { 3 pow 2u } + }, + m(27) * NumberedPolynomial { + m(22) with {} + m(26) with { 1 pow 3u } + m(13) with { 2 pow 1u } + m(15) with { 1 pow 1u } + m(26) with { 3 pow 2u } + }, + "test 1" + ) + assertEquals( + NumberedPolynomial { + m(0) with {} + m(0) with { 1 pow 3u } + m(0) with { 2 pow 1u } + m(0) with { 1 pow 1u } + m(0) with { 3 pow 2u } + }, + m(15) * NumberedPolynomial { + m(7) with {} + m(0) with { 1 pow 3u } + m(49) with { 2 pow 1u } + m(21) with { 1 pow 1u } + m(14) with { 3 pow 2u } + }, + "test 2" + ) + assertEquals( + NumberedPolynomial { + m(0) with {} + m(0) with { 1 pow 3u } + m(0) with { 2 pow 1u } + m(0) with { 1 pow 1u } + m(0) with { 3 pow 2u } + }, + m(0) * NumberedPolynomial { + m(22) with {} + m(26) with { 1 pow 3u } + m(13) with { 2 pow 1u } + m(15) with { 1 pow 1u } + m(26) with { 3 pow 2u } + }, + "test 3" + ) + assertEquals( + NumberedPolynomial { + m(22) with {} + m(26) with { 1 pow 3u } + m(13) with { 2 pow 1u } + m(15) with { 1 pow 1u } + m(26) with { 3 pow 2u } + }, + m(1) * NumberedPolynomial { + m(22) with {} + m(26) with { 1 pow 3u } + m(13) with { 2 pow 1u } + m(15) with { 1 pow 1u } + m(26) with { 3 pow 2u } + }, + "test 4" + ) + } + } + @Test + fun test_Polynomial_unaryMinus() { + RationalField.numberedPolynomialSpace { + assertEquals( + NumberedPolynomial { + Rational(-5, 9) with { 1 pow 5u } + Rational(8, 9) with {} + Rational(8, 7) with { 7 pow 13u } + }, + -NumberedPolynomial { + Rational(5, 9) with { 1 pow 5u } + Rational(-8, 9) with {} + Rational(-8, 7) with { 7 pow 13u } + }, + "test 1" + ) + assertEquals( + NumberedPolynomial { + Rational(-5, 9) with { 3 pow 7u } + Rational(8, 9) with {} + Rational(8, 7) with { 1 pow 3u } + Rational(0) with { 2 pow 4u } + Rational(0) with { 1 pow 5u } + }, + -NumberedPolynomial { + Rational(5, 9) with { 3 pow 7u } + Rational(-8, 9) with {} + Rational(-8, 7) with { 1 pow 3u } + Rational(0) with { 2 pow 4u } + Rational(0) with { 1 pow 5u } + }, + "test 2" + ) + } + } + @Test + fun test_Polynomial_Polynomial_plus() { + RationalField.numberedPolynomialSpace { + assertEquals( + NumberedPolynomial { + Rational(-17, 2) with {} + Rational(-1, 3) with { 1 pow 1u } + Rational(-25, 21) with { 1 pow 2u } + Rational(146, 63) with { 2 pow 1u } + Rational(-3, 5) with { 1 pow 1u; 2 pow 1u } + Rational(61, 15) with { 1 pow 2u; 2 pow 1u } + Rational(157, 63) with { 2 pow 2u } + Rational(-55, 21) with { 1 pow 1u; 2 pow 2u } + Rational(11, 24) with { 1 pow 2u; 2 pow 2u } + }, + NumberedPolynomial { + Rational(6, 4) with {} + Rational(-2, 6) with { 1 pow 1u } + Rational(10, 6) with { 1 pow 2u } + Rational(17, 7) with { 2 pow 1u } + Rational(-7, 7) with { 1 pow 1u; 2 pow 1u } + Rational(12, 5) with { 1 pow 2u; 2 pow 1u } + Rational(12, 7) with { 2 pow 2u } + Rational(-10, 3) with { 1 pow 1u; 2 pow 2u } + Rational(9, 8) with { 1 pow 2u; 2 pow 2u } + } + NumberedPolynomial { + Rational(-20, 2) with {} + Rational(0, 9) with { 1 pow 1u } + Rational(-20, 7) with { 1 pow 2u } + Rational(-1, 9) with { 2 pow 1u } + Rational(2, 5) with { 1 pow 1u; 2 pow 1u } + Rational(10, 6) with { 1 pow 2u; 2 pow 1u } + Rational(7, 9) with { 2 pow 2u } + Rational(5, 7) with { 1 pow 1u; 2 pow 2u } + Rational(-2, 3) with { 1 pow 2u; 2 pow 2u } + }, + "test 1" + ) + assertEquals( + NumberedPolynomial { + Rational(-17, 2) with {} + Rational(-1, 3) with { 1 pow 1u } + Rational(-25, 21) with { 1 pow 2u } + Rational(-1, 9) with { 2 pow 1u } + Rational(2, 5) with { 1 pow 1u; 2 pow 1u } + Rational(10, 6) with { 1 pow 2u; 2 pow 1u } + Rational(157, 63) with { 2 pow 2u } + Rational(-55, 21) with { 1 pow 1u; 2 pow 2u } + Rational(11, 24) with { 1 pow 2u; 2 pow 2u } + }, + NumberedPolynomial { + Rational(6, 4) with {} + Rational(-2, 6) with { 1 pow 1u } + Rational(10, 6) with { 1 pow 2u } + Rational(12, 7) with { 2 pow 2u } + Rational(-10, 3) with { 1 pow 1u; 2 pow 2u } + Rational(9, 8) with { 1 pow 2u; 2 pow 2u } + } + NumberedPolynomial { + Rational(-20, 2) with {} + Rational(0, 9) with { 1 pow 1u } + Rational(-20, 7) with { 1 pow 2u } + Rational(-1, 9) with { 2 pow 1u } + Rational(2, 5) with { 1 pow 1u; 2 pow 1u } + Rational(10, 6) with { 1 pow 2u; 2 pow 1u } + Rational(7, 9) with { 2 pow 2u } + Rational(5, 7) with { 1 pow 1u; 2 pow 2u } + Rational(-2, 3) with { 1 pow 2u; 2 pow 2u } + }, + "test 2" + ) + assertEquals( + NumberedPolynomial { + Rational(-17, 2) with {} + Rational(-1, 3) with { 1 pow 1u } + Rational(-25, 21) with { 1 pow 2u } + Rational(-1, 9) with { 2 pow 1u } + Rational(2, 5) with { 1 pow 1u; 2 pow 1u } + Rational(10, 6) with { 1 pow 2u; 2 pow 1u } + Rational(12, 7) with { 2 pow 2u } + Rational(-10, 3) with { 1 pow 1u; 2 pow 2u } + Rational(9, 8) with { 1 pow 2u; 2 pow 2u } + }, + NumberedPolynomial { + Rational(6, 4) with {} + Rational(-2, 6) with { 1 pow 1u } + Rational(10, 6) with { 1 pow 2u } + Rational(12, 7) with { 2 pow 2u } + Rational(-10, 3) with { 1 pow 1u; 2 pow 2u } + Rational(9, 8) with { 1 pow 2u; 2 pow 2u } + } + NumberedPolynomial { + Rational(-20, 2) with {} + Rational(0, 9) with { 1 pow 1u } + Rational(-20, 7) with { 1 pow 2u } + Rational(-1, 9) with { 2 pow 1u } + Rational(2, 5) with { 1 pow 1u; 2 pow 1u } + Rational(10, 6) with { 1 pow 2u; 2 pow 1u } + Rational(0) with { 2 pow 2u } + Rational(0) with { 1 pow 1u; 2 pow 2u } + Rational(0) with { 1 pow 2u; 2 pow 2u } + }, + "test 3" + ) + assertEquals( + NumberedPolynomial { + Rational(0) with {} + Rational(0) with { 1 pow 1u } + Rational(0) with { 1 pow 2u } + Rational(0) with { 2 pow 1u } + Rational(0) with { 1 pow 1u; 2 pow 1u } + Rational(0) with { 1 pow 2u; 2 pow 1u } + Rational(0) with { 2 pow 2u } + Rational(0) with { 1 pow 1u; 2 pow 2u } + Rational(0) with { 1 pow 2u; 2 pow 2u } + }, + NumberedPolynomial { + Rational(6, 4) with {} + Rational(-2, 6) with { 1 pow 1u } + Rational(10, 6) with { 1 pow 2u } + Rational(17, 7) with { 2 pow 1u } + Rational(-7, 7) with { 1 pow 1u; 2 pow 1u } + Rational(12, 5) with { 1 pow 2u; 2 pow 1u } + Rational(12, 7) with { 2 pow 2u } + Rational(-10, 3) with { 1 pow 1u; 2 pow 2u } + Rational(9, 8) with { 1 pow 2u; 2 pow 2u } + } + NumberedPolynomial { + Rational(-6, 4) with {} + Rational(2, 6) with { 1 pow 1u } + Rational(-10, 6) with { 1 pow 2u } + Rational(-17, 7) with { 2 pow 1u } + Rational(7, 7) with { 1 pow 1u; 2 pow 1u } + Rational(-12, 5) with { 1 pow 2u; 2 pow 1u } + Rational(-12, 7) with { 2 pow 2u } + Rational(10, 3) with { 1 pow 1u; 2 pow 2u } + Rational(-9, 8) with { 1 pow 2u; 2 pow 2u } + }, + "test 4" + ) + } + } + @Test + fun test_Polynomial_Polynomial_minus() { + RationalField.numberedPolynomialSpace { + assertEquals( + NumberedPolynomial { + Rational(-17, 2) with {} + Rational(-1, 3) with { 1 pow 1u } + Rational(-25, 21) with { 1 pow 2u } + Rational(146, 63) with { 2 pow 1u } + Rational(-3, 5) with { 1 pow 1u; 2 pow 1u } + Rational(61, 15) with { 1 pow 2u; 2 pow 1u } + Rational(157, 63) with { 2 pow 2u } + Rational(-55, 21) with { 1 pow 1u; 2 pow 2u } + Rational(11, 24) with { 1 pow 2u; 2 pow 2u } + }, + NumberedPolynomial { + Rational(6, 4) with {} + Rational(-2, 6) with { 1 pow 1u } + Rational(10, 6) with { 1 pow 2u } + Rational(17, 7) with { 2 pow 1u } + Rational(-7, 7) with { 1 pow 1u; 2 pow 1u } + Rational(12, 5) with { 1 pow 2u; 2 pow 1u } + Rational(12, 7) with { 2 pow 2u } + Rational(-10, 3) with { 1 pow 1u; 2 pow 2u } + Rational(9, 8) with { 1 pow 2u; 2 pow 2u } + } - NumberedPolynomial { + Rational(20, 2) with {} + Rational(0, 9) with { 1 pow 1u } + Rational(20, 7) with { 1 pow 2u } + Rational(1, 9) with { 2 pow 1u } + Rational(-2, 5) with { 1 pow 1u; 2 pow 1u } + Rational(-10, 6) with { 1 pow 2u; 2 pow 1u } + Rational(-7, 9) with { 2 pow 2u } + Rational(-5, 7) with { 1 pow 1u; 2 pow 2u } + Rational(2, 3) with { 1 pow 2u; 2 pow 2u } + }, + "test 1" + ) + assertEquals( + NumberedPolynomial { + Rational(-17, 2) with {} + Rational(-1, 3) with { 1 pow 1u } + Rational(-25, 21) with { 1 pow 2u } + Rational(-1, 9) with { 2 pow 1u } + Rational(2, 5) with { 1 pow 1u; 2 pow 1u } + Rational(10, 6) with { 1 pow 2u; 2 pow 1u } + Rational(157, 63) with { 2 pow 2u } + Rational(-55, 21) with { 1 pow 1u; 2 pow 2u } + Rational(11, 24) with { 1 pow 2u; 2 pow 2u } + }, + NumberedPolynomial { + Rational(6, 4) with {} + Rational(-2, 6) with { 1 pow 1u } + Rational(10, 6) with { 1 pow 2u } + Rational(12, 7) with { 2 pow 2u } + Rational(-10, 3) with { 1 pow 1u; 2 pow 2u } + Rational(9, 8) with { 1 pow 2u; 2 pow 2u } + } - NumberedPolynomial { + Rational(20, 2) with {} + Rational(0, 9) with { 1 pow 1u } + Rational(20, 7) with { 1 pow 2u } + Rational(1, 9) with { 2 pow 1u } + Rational(-2, 5) with { 1 pow 1u; 2 pow 1u } + Rational(-10, 6) with { 1 pow 2u; 2 pow 1u } + Rational(-7, 9) with { 2 pow 2u } + Rational(-5, 7) with { 1 pow 1u; 2 pow 2u } + Rational(2, 3) with { 1 pow 2u; 2 pow 2u } + }, + "test 2" + ) + assertEquals( + NumberedPolynomial { + Rational(-17, 2) with {} + Rational(-1, 3) with { 1 pow 1u } + Rational(-25, 21) with { 1 pow 2u } + Rational(-1, 9) with { 2 pow 1u } + Rational(2, 5) with { 1 pow 1u; 2 pow 1u } + Rational(10, 6) with { 1 pow 2u; 2 pow 1u } + Rational(12, 7) with { 2 pow 2u } + Rational(-10, 3) with { 1 pow 1u; 2 pow 2u } + Rational(9, 8) with { 1 pow 2u; 2 pow 2u } + }, + NumberedPolynomial { + Rational(6, 4) with {} + Rational(-2, 6) with { 1 pow 1u } + Rational(10, 6) with { 1 pow 2u } + Rational(12, 7) with { 2 pow 2u } + Rational(-10, 3) with { 1 pow 1u; 2 pow 2u } + Rational(9, 8) with { 1 pow 2u; 2 pow 2u } + } - NumberedPolynomial { + Rational(20, 2) with {} + Rational(0, 9) with { 1 pow 1u } + Rational(20, 7) with { 1 pow 2u } + Rational(1, 9) with { 2 pow 1u } + Rational(-2, 5) with { 1 pow 1u; 2 pow 1u } + Rational(-10, 6) with { 1 pow 2u; 2 pow 1u } + Rational(0) with { 2 pow 2u } + Rational(0) with { 1 pow 1u; 2 pow 2u } + Rational(0) with { 1 pow 2u; 2 pow 2u } + }, + "test 3" + ) + assertEquals( + NumberedPolynomial { + Rational(0) with {} + Rational(0) with { 1 pow 1u } + Rational(0) with { 1 pow 2u } + Rational(0) with { 2 pow 1u } + Rational(0) with { 1 pow 1u; 2 pow 1u } + Rational(0) with { 1 pow 2u; 2 pow 1u } + Rational(0) with { 2 pow 2u } + Rational(0) with { 1 pow 1u; 2 pow 2u } + Rational(0) with { 1 pow 2u; 2 pow 2u } + }, + NumberedPolynomial { + Rational(6, 4) with {} + Rational(-2, 6) with { 1 pow 1u } + Rational(10, 6) with { 1 pow 2u } + Rational(17, 7) with { 2 pow 1u } + Rational(-7, 7) with { 1 pow 1u; 2 pow 1u } + Rational(12, 5) with { 1 pow 2u; 2 pow 1u } + Rational(12, 7) with { 2 pow 2u } + Rational(-10, 3) with { 1 pow 1u; 2 pow 2u } + Rational(9, 8) with { 1 pow 2u; 2 pow 2u } + } - NumberedPolynomial { + Rational(6, 4) with {} + Rational(-2, 6) with { 1 pow 1u } + Rational(10, 6) with { 1 pow 2u } + Rational(17, 7) with { 2 pow 1u } + Rational(-7, 7) with { 1 pow 1u; 2 pow 1u } + Rational(12, 5) with { 1 pow 2u; 2 pow 1u } + Rational(12, 7) with { 2 pow 2u } + Rational(-10, 3) with { 1 pow 1u; 2 pow 2u } + Rational(9, 8) with { 1 pow 2u; 2 pow 2u } + }, + "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 { + m(1) with { 1 pow 3u } + m(1) with { 2 pow 3u } + m(1) with { 3 pow 3u } + m(0) with { 1 pow 1u; 2 pow 2u } + m(0) with { 2 pow 1u; 3 pow 2u } + m(0) with { 3 pow 1u; 1 pow 2u } + m(0) with { 1 pow 1u; 3 pow 2u } + m(0) with { 2 pow 1u; 1 pow 2u } + m(0) with { 3 pow 1u; 2 pow 2u } + m(-3) with { 1 pow 1u; 2 pow 1u; 3 pow 1u } + }, + NumberedPolynomial { + m(1) with { 1 pow 1u } + m(1) with { 2 pow 1u } + m(1) with { 3 pow 1u } + } * NumberedPolynomial { + m(1) with { 1 pow 2u } + m(1) with { 2 pow 2u } + m(1) with { 3 pow 2u } + m(-1) with { 1 pow 1u; 2 pow 1u } + m(-1) with { 2 pow 1u; 3 pow 1u } + m(-1) with { 3 pow 1u; 1 pow 1u } + }, + "test 1" + ) + // Spoiler: 5 * 7 = 0 + assertEquals( + NumberedPolynomial { + m(0) with { 1 pow 2u } + m(0) with { 2 pow 2u } + m(0) with { 3 pow 2u } + m(0) with { 1 pow 1u; 2 pow 1u } + m(0) with { 2 pow 1u; 3 pow 1u } + m(0) with { 3 pow 1u; 1 pow 1u } + }, + NumberedPolynomial { + m(5) with { 1 pow 1u } + m(-25) with { 2 pow 1u } + m(10) with { 3 pow 1u } + } * NumberedPolynomial { + m(21) with { 1 pow 1u } + m(14) with { 2 pow 1u } + m(-7) with { 3 pow 1u } + }, + "test 2" + ) + } + } +} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt index 89764db46..afd2b5add 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt @@ -7,6 +7,7 @@ package space.kscience.kmath.test.misc import space.kscience.kmath.functions.ListPolynomial import space.kscience.kmath.functions.ListPolynomialSpace +import space.kscience.kmath.functions.PolynomialSpaceOverRing import space.kscience.kmath.operations.Ring @@ -135,4 +136,7 @@ class IntModuloRing : Ring { 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) }) \ No newline at end of file + ListPolynomial(coefs.map { IntModulo(it, modulus) }) + +fun IntModuloRing.m(arg: Int) = IntModulo(arg, modulus) +fun PolynomialSpaceOverRing.m(arg: Int) = IntModulo(arg, ring.modulus) \ No newline at end of file -- 2.34.1 From 1ea336b70ea5a0f44722071b29193215c1460b14 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Fri, 17 Jun 2022 22:07:54 +0300 Subject: [PATCH 098/275] Added some test of NumberedPolynomial utilities. --- .../functions/NumberedPolynomialUtilTest.kt | 293 ++++++++++++++++++ .../kscience/kmath/test/misc/assertion.kt | 14 + 2 files changed, 307 insertions(+) create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/assertion.kt diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt new file mode 100644 index 000000000..ecad6198e --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt @@ -0,0 +1,293 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.test.misc.Rational +import space.kscience.kmath.test.misc.RationalField +import space.kscience.kmath.test.misc.assertContentEquals +import kotlin.test.Test +import kotlin.test.assertEquals + + +class NumberedPolynomialUtilTest { + @Test + fun test_substitute_Double_Map() { + assertContentEquals( + mapOf(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 + )).coefficients, + 0.001, + "test 1" + ) + assertContentEquals( + mapOf( + 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()).coefficients, + 0.001, + "test 2" + ) + assertContentEquals( + mapOf( + 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 + )).coefficients, + 0.001, + "test 3" + ) + assertContentEquals( + mapOf( + 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 + )).coefficients, + 0.001, + "test 4" + ) + assertContentEquals( + mapOf( + 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, + )).coefficients, + 0.001, + "test 5" + ) + assertContentEquals( + mapOf( + 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 + )).coefficients, + 0.001, + "test 6" + ) + } + @Test + fun test_substitute_Constant() { + 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" + ) + // 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 3" + ) + // 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(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), + ), + 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()), + "test 4" + ) + } + @Test + fun test_substitute_Polynomial() { + 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+-2%2F5%2C+y+%3D+12%2F9 + 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" + ) + } +} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/assertion.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/assertion.kt new file mode 100644 index 000000000..52ecf416a --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/assertion.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.test.misc + +import kotlin.test.assertEquals + + +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) +} \ No newline at end of file -- 2.34.1 From 680d23ddcb0c3e11ea779146f3d2ced2d8c741be Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sat, 18 Jun 2022 01:25:14 +0300 Subject: [PATCH 099/275] Last sift. Cleaned up labeled structures. --- .../kmath/functions/LabeledPolynomial.kt | 621 ++++++++++++++++++ .../functions/LabeledRationalFunction.kt | 96 +++ .../kmath/functions/ListPolynomial.kt | 2 +- .../kmath/functions/NumberedPolynomial.kt | 11 +- .../kmath/functions/labeledConstructors.kt | 518 +++++++++++++++ .../kscience/kmath/functions/labeledUtil.kt | 327 +++++++++ .../kmath/functions/numberedConstructors.kt | 40 +- .../kscience/kmath/functions/numberedUtil.kt | 18 +- 8 files changed, 1584 insertions(+), 49 deletions(-) create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt new file mode 100644 index 000000000..b0c54502d --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -0,0 +1,621 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.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. + */ + public val coefficients: Map, C> +) : Polynomial { + 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( + mapOf(this@plus to 1U) to constantOne, + )) + else LabeledPolynomialAsIs(mapOf( + mapOf(this@plus to 1U) to constantOne, + emptyMap() to constantOne * other, + )) + /** + * 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( + mapOf(this@minus to 1U) to -constantOne, + )) + else LabeledPolynomialAsIs(mapOf( + mapOf(this@minus to 1U) to -constantOne, + emptyMap() to constantOne * other, + )) + /** + * 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( + mapOf(this to 1U) to constantOne * other, + )) + + /** + * 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( + mapOf(other to 1U) to constantOne, + )) + else LabeledPolynomialAsIs(mapOf( + mapOf(other to 1U) to constantOne, + emptyMap() to constantOne * this@plus, + )) + /** + * 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( + mapOf(other to 1U) to -constantOne, + )) + else LabeledPolynomialAsIs(mapOf( + 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( + mapOf(other to 1U) to constantOne * this@times, + )) + + /** + * 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 = + if (other == 0) this + else with(coefficients) { + if (isEmpty()) LabeledPolynomialAsIs(mapOf(emptyMap() to other.asConstant())) + else LabeledPolynomialAsIs( + toMutableMap() + .apply { + val degs = emptyMap() + + this[degs] = getOrElse(degs) { constantZero } + 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 = + if (other == 0) this + else with(coefficients) { + if (isEmpty()) LabeledPolynomialAsIs(mapOf(emptyMap() to (-other).asConstant())) + else LabeledPolynomialAsIs( + toMutableMap() + .apply { + val degs = emptyMap() + + this[degs] = getOrElse(degs) { constantZero } - 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 = + if (other == 0) zero + else LabeledPolynomial( + coefficients + .toMutableMap() + .apply { + for (degs in keys) this[degs] = this[degs]!! * 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 = + if (this == 0) other + else with(other.coefficients) { + if (isEmpty()) LabeledPolynomialAsIs(mapOf(emptyMap() to this@plus.asConstant())) + else LabeledPolynomialAsIs( + toMutableMap() + .apply { + val degs = emptyMap() + + this[degs] = this@plus + getOrElse(degs) { constantZero } + } + ) + } + /** + * 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 = + if (this == 0) other + else with(other.coefficients) { + if (isEmpty()) LabeledPolynomialAsIs(mapOf(emptyMap() to this@minus.asConstant())) + else LabeledPolynomialAsIs( + toMutableMap() + .apply { + forEach { (key, value) -> if (key.isNotEmpty()) this[key] = -value } + + val degs = emptyMap() + + this[degs] = this@minus - getOrElse(degs) { constantZero } + } + ) + } + /** + * 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 = + if (this == 0) zero + else LabeledPolynomial( + other.coefficients + .toMutableMap() + .apply { + for (degs in keys) this[degs] = this@times * this[degs]!! + } + ) + + /** + * Converts the integer [value] to polynomial. + */ + public override fun number(value: Int): LabeledPolynomial = number(constantNumber(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( + 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( + 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( + 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( + 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( + 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( + 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 = + with(other.coefficients) { + if (isEmpty()) LabeledPolynomialAsIs(mapOf(emptyMap() to this@plus)) + else LabeledPolynomialAsIs( + toMutableMap() + .apply { + val degs = emptyMap() + + this[degs] = this@plus + getOrElse(degs) { constantZero } + } + ) + } + /** + * Returns difference between the constant represented as a polynomial and the polynomial. + */ + override operator fun C.minus(other: LabeledPolynomial): LabeledPolynomial = + with(other.coefficients) { + if (isEmpty()) LabeledPolynomialAsIs(mapOf(emptyMap() to this@minus)) + else LabeledPolynomialAsIs( + toMutableMap() + .apply { + forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } + + val degs = emptyMap() + + this[degs] = this@minus - getOrElse(degs) { constantZero } + } + ) + } + /** + * Returns product of the constant represented as a polynomial and the polynomial. + */ + override operator fun C.times(other: LabeledPolynomial): LabeledPolynomial = + LabeledPolynomialAsIs( + other.coefficients + .toMutableMap() + .apply { + for (degs in keys) this[degs] = this@times * this[degs]!! + } + ) + + /** + * Returns sum of the constant represented as a polynomial and the polynomial. + */ + override operator fun LabeledPolynomial.plus(other: C): LabeledPolynomial = + with(coefficients) { + if (isEmpty()) LabeledPolynomialAsIs(mapOf(emptyMap() to other)) + else LabeledPolynomialAsIs( + toMutableMap() + .apply { + val degs = emptyMap() + + this[degs] = getOrElse(degs) { constantZero } + other + } + ) + } + /** + * Returns difference between the constant represented as a polynomial and the polynomial. + */ + override operator fun LabeledPolynomial.minus(other: C): LabeledPolynomial = + with(coefficients) { + if (isEmpty()) LabeledPolynomialAsIs(mapOf(emptyMap() to other)) + else LabeledPolynomialAsIs( + toMutableMap() + .apply { + forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } + + val degs = emptyMap() + + this[degs] = getOrElse(degs) { constantZero } - other + } + ) + } + /** + * Returns product of the constant represented as a polynomial and the polynomial. + */ + override operator fun LabeledPolynomial.times(other: C): LabeledPolynomial = + LabeledPolynomialAsIs( + coefficients + .toMutableMap() + .apply { + for (degs in keys) this[degs] = this[degs]!! * other + } + ) + + /** + * Converts the constant [value] to polynomial. + */ + public override fun number(value: C): LabeledPolynomial = + LabeledPolynomial(mapOf(emptyMap() to value)) + + /** + * Represents the variable as a monic monomial. + */ + public override operator fun Symbol.unaryPlus(): LabeledPolynomial = + LabeledPolynomialAsIs(mapOf( + 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( + 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( + mapOf(this to 1U) to constantOne * 2 + )) + else LabeledPolynomialAsIs(mapOf( + 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( + 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( + mapOf(this to 2U) to constantOne + )) + else LabeledPolynomialAsIs(mapOf( + 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 = + with(other.coefficients) { + if (isEmpty()) LabeledPolynomialAsIs(mapOf(mapOf(this@plus to 1u) to constantOne)) + else LabeledPolynomialAsIs( + toMutableMap() + .apply { + val degs = mapOf(this@plus to 1U) + + this[degs] = constantOne + getOrElse(degs) { constantZero } + } + ) + } + /** + * Returns difference between the variable represented as a monic monomial and the polynomial. + */ + public override operator fun Symbol.minus(other: LabeledPolynomial): LabeledPolynomial = + with(other.coefficients) { + if (isEmpty()) LabeledPolynomialAsIs(mapOf(mapOf(this@minus to 1u) to constantOne)) + else LabeledPolynomialAsIs( + toMutableMap() + .apply { + val degs = mapOf(this@minus to 1U) + + forEach { (degs, c) -> if(degs != degs) this[degs] = -c } + + this[degs] = constantOne - getOrElse(degs) { constantZero } + } + ) + } + /** + * 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.toMutableMap().also{ it[this] = if (this in it) it[this]!! + 1U else 1U } } + ) + + /** + * Returns sum of the polynomial and the variable represented as a monic monomial. + */ + public override operator fun LabeledPolynomial.plus(other: Symbol): LabeledPolynomial = + with(coefficients) { + if (isEmpty()) LabeledPolynomialAsIs(mapOf(mapOf(other to 1u) to constantOne)) + else LabeledPolynomialAsIs( + toMutableMap() + .apply { + val degs = mapOf(other to 1U) + + this[degs] = constantOne + getOrElse(degs) { constantZero } + } + ) + } + /** + * Returns difference between the polynomial and the variable represented as a monic monomial. + */ + public override operator fun LabeledPolynomial.minus(other: Symbol): LabeledPolynomial = + with(coefficients) { + if (isEmpty()) LabeledPolynomialAsIs(mapOf(mapOf(other to 1u) to constantOne)) + else LabeledPolynomialAsIs( + toMutableMap() + .apply { + val degs = mapOf(other to 1U) + + this[degs] = constantOne - getOrElse(degs) { constantZero } + } + ) + } + /** + * 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.toMutableMap().also{ it[other] = if (other in it) it[other]!! + 1U else 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( + buildMap(coefficients.size + other.coefficients.size) { + other.coefficients.mapValuesTo(this) { it.value } + other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value } + } + ) + /** + * Returns difference of the polynomials. + */ + override operator fun LabeledPolynomial.minus(other: LabeledPolynomial): LabeledPolynomial = + LabeledPolynomialAsIs( + buildMap(coefficients.size + other.coefficients.size) { + other.coefficients.mapValuesTo(this) { it.value } + other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value } + } + ) + /** + * 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 = degs1.toMutableMap() + degs2.mapValuesTo(degs) { (variable, deg) -> degs.getOrElse(variable) { 0u } + deg } + val c = c1 * c2 + this[degs] = if (degs in this) this[degs]!! + c else c + } + } + ) + + /** + * Instance of zero polynomial (zero of the polynomial ring). + */ + override val zero: LabeledPolynomial = LabeledPolynomialAsIs(mapOf(emptyMap() to constantZero)) + /** + * Instance of unit polynomial (unit of the polynomial ring). + */ + override val one: LabeledPolynomial = LabeledPolynomialAsIs(mapOf(emptyMap() to constantOne)) + + /** + * 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.entries.forEach { (degs, _) -> + degs.mapValuesTo(this) { (variable, deg) -> + max(getOrElse(variable) { 0u }, deg) + } + } + } + /** + * 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. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun LabeledPolynomial.substitute(arguments: Map): LabeledPolynomial = substitute(ring, arguments) + /** + * Substitutes provided arguments [arguments] into [this] polynomial. + */ + @Suppress("NOTHING_TO_INLINE") + @JvmName("substitutePolynomial") + public inline fun LabeledPolynomial.substitute(arguments: Map>) : LabeledPolynomial = substitute(ring, arguments) +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt new file mode 100644 index 000000000..03f323813 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt @@ -0,0 +1,96 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.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 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, +) : + MultivariateRationalFunctionalSpaceOverMultivariatePolynomialSpace< + 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. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun LabeledPolynomial.substitute(argument: Map): LabeledPolynomial = substitute(ring, argument) + /** + * Substitutes provided polynomial [argument] into [this] polynomial. + */ + @Suppress("NOTHING_TO_INLINE") + @JvmName("substitutePolynomial") + public inline fun LabeledPolynomial.substitute(argument: Map>): LabeledPolynomial = substitute(ring, argument) + /** + * Substitutes provided rational function [argument] into [this] polynomial. + */ + @Suppress("NOTHING_TO_INLINE") + @JvmName("substituteRationalFunction") + public inline fun LabeledPolynomial.substitute(argument: Map>): LabeledRationalFunction = substitute(ring, argument) + /** + * Substitutes provided constant [argument] into [this] rational function. + */ + @Suppress("NOTHING_TO_INLINE") + public inline fun LabeledRationalFunction.substitute(argument: Map): LabeledRationalFunction = substitute(ring, argument) + /** + * Substitutes provided polynomial [argument] into [this] rational function. + */ + @Suppress("NOTHING_TO_INLINE") + @JvmName("substitutePolynomial") + public inline fun LabeledRationalFunction.substitute(argument: Map>): LabeledRationalFunction = substitute(ring, argument) + /** + * Substitutes provided rational function [argument] into [this] rational function. + */ + @Suppress("NOTHING_TO_INLINE") + @JvmName("substituteRationalFunction") + public inline fun LabeledRationalFunction.substitute(argument: Map>): LabeledRationalFunction = substitute(ring, argument) +} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt index b3f1eb8f7..8db93cbb1 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt @@ -15,7 +15,7 @@ import kotlin.math.min /** * Represents univariate polynomial that stores its coefficients in a [List]. * - * @param coefficients constant is the leftmost coefficient. + * @param C the type of constants. */ public data class ListPolynomial( /** diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index 02a3af683..eadeb68ab 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -12,7 +12,7 @@ import kotlin.math.max /** - * Represents univariate polynomial that stores its coefficients in a [Map] and terms' signatures in a [List]. + * Represents multivariate polynomial that stores its coefficients in a [Map] and terms' signatures in a [List]. * * @param C the type of constants. */ @@ -20,10 +20,11 @@ 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 pair - * "key-value" in the map, where the value is the coefficients `a` and the key is a list that associates index of - * every variable in the monomial with multiplicity of the variable occurring in the monomial. For example - * coefficients of a polynomial `5 x_1^2 x_3^3 - 6 x_2` can be represented as + * 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 + diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt new file mode 100644 index 000000000..47325c4bb --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt @@ -0,0 +1,518 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +@file:Suppress("FunctionName", "NOTHING_TO_INLINE") + +package space.kscience.kmath.functions + +import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.Ring + + +/** + * 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. + */ +public fun LabeledPolynomial(coefs: Map, C>, add: (C, C) -> C) : LabeledPolynomial { + val fixedCoefs = mutableMapOf, C>() + + for (entry in coefs) { + val key = entry.key.cleanUp() + val value = entry.value + fixedCoefs[key] = if (key in fixedCoefs) add(fixedCoefs[key]!!, value) else value + } + + return LabeledPolynomial(fixedCoefs) +} + +/** + * 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. + */ +public fun LabeledPolynomial(pairs: Collection, C>>, add: (C, C) -> C) : LabeledPolynomial { + val fixedCoefs = mutableMapOf, C>() + + for (entry in pairs) { + val key = entry.first.cleanUp() + val value = entry.second + fixedCoefs[key] = if (key in fixedCoefs) add(fixedCoefs[key]!!, value) else value + } + + return LabeledPolynomial(fixedCoefs) +} + +/** + * 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. + */ +public fun LabeledPolynomial(vararg pairs: Pair, C>, add: (C, C) -> C) : LabeledPolynomial { + val fixedCoefs = mutableMapOf, C>() + + for (entry in pairs) { + val key = entry.first.cleanUp() + val value = entry.second + fixedCoefs[key] = if (key in fixedCoefs) add(fixedCoefs[key]!!, value) else value + } + + return LabeledPolynomial(fixedCoefs) +} + +// 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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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 numberedPolynomial : NumberedPolynomial = NumberedPolynomial { + * 5 { a inPowerOf 2u; c inPowerOf 3u } // 5 a^2 c^3 + + * (-6) { b inPowerOf 1u } // (-6) b^1 + * } + * } + * ``` + */ +@DslMarker +@UnstableKMathAPI +internal annotation class LabeledPolynomialConstructorDSL + +/** + * Builder of [LabeledPolynomial] signature. It should be used as an implicit context for lambdas that describe term signature. + */ +@UnstableKMathAPI +@LabeledPolynomialConstructorDSL +public class LabeledPolynomialTermSignatureBuilder { + /** + * 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) { + signature[this] = deg + } + /** + * Declares power of [this] variable of degree [deg]. + * + * Declaring another power of the same variable will increase its degree by received degree. + */ + @Suppress("NOTHING_TO_INLINE") + 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. + */ + @Suppress("NOTHING_TO_INLINE") + 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. + */ + @Suppress("NOTHING_TO_INLINE") + 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 +public class LabeledPolynomialBuilder( + /** + * 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 = 0 +) { + /** + * 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> = LinkedHashMap(initialCapacity) + + /** + * 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[signature] = if (signature in coefficients) add(coefficients[signature]!!, this@with) else this@with + } + /** + * 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. + */ + @Suppress("NOTHING_TO_INLINE") + public inline infix fun C.with(noinline block: LabeledPolynomialTermSignatureBuilder.() -> 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: LabeledPolynomialTermSignatureBuilder.() -> Unit): Unit = + this with LabeledPolynomialTermSignatureBuilder().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 x_1^2 x_3^3 - 6 x_2` can be described as +// * ``` +// * Int.algebra { +// * val LabeledPolynomial : LabeledPolynomial = LabeledPolynomial { +// * 5 { 1 inPowerOf 2u; 3 inPowerOf 3u } // 5 x_1^2 x_3^3 + +// * (-6) { 2 inPowerOf 1u } // (-6) x_2^1 +// * } +// * } +// * ``` +// */ +// 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.LabeledPolynomial(initialCapacity: Int = 0, 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 x_1^2 x_3^3 - 6 x_2` can be described as + * ``` + * Int.algebra { + * val LabeledPolynomial : LabeledPolynomial = LabeledPolynomial { + * 5 { 1 inPowerOf 2u; 3 inPowerOf 3u } // 5 x_1^2 x_3^3 + + * (-6) { 2 inPowerOf 1u } // (-6) x_2^1 + * } + * } + * ``` + */ +@UnstableKMathAPI +public inline fun > LabeledPolynomialSpace.LabeledPolynomial(initialCapacity: Int = 0, block: LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = LabeledPolynomialBuilder({ 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 x_1^2 x_3^3 - 6 x_2` can be described as + * ``` + * Int.algebra { + * val LabeledPolynomial : LabeledPolynomial = LabeledPolynomial { + * 5 { 1 inPowerOf 2u; 3 inPowerOf 3u } // 5 x_1^2 x_3^3 + + * (-6) { 2 inPowerOf 1u } // (-6) x_2^1 + * } + * } + * ``` + */ +@UnstableKMathAPI +public inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(initialCapacity: Int = 0, block: LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = LabeledPolynomialBuilder({ 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 [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-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt new file mode 100644 index 000000000..39c781a14 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt @@ -0,0 +1,327 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.Field +import space.kscience.kmath.operations.invoke +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.algebra +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract +import kotlin.jvm.JvmName + + +/** + * Creates a [LabeledPolynomialSpace] over a received ring. + */ +public fun > A.labeledPolynomialSpace(): LabeledPolynomialSpace = + 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 fun > A.labeledRationalFunctionSpace(): LabeledRationalFunctionSpace = + 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) + } + this[newDegs] = if (newDegs in this) this[newDegs]!! + newC else newC + } + } + ) +} + +/** + * 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) + } + this[newDegs] = if (newDegs in this) this[newDegs]!! + newC else newC + } + } + ) +} + +/** + * 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.size) { + 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.size) { + 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.size) { + 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 = buildMap(degs.size + 1) { + put(variable, 1u) + for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) + } + 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 = buildMap(degs.size + 1) { + put(variable, order) + for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) + } + 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 = buildMap(degs.size + 1) { + for ((variable, order) in filteredVariablesAndOrders) put(variable, order) + for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) + } + 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-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt index 37d5d7fb6..4850e6cec 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.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("FunctionName", "NOTHING_TO_INLINE") + package space.kscience.kmath.functions import space.kscience.kmath.misc.UnstableKMathAPI @@ -17,7 +19,6 @@ internal fun List.cleanUp() = subList(0, indexOfLast { it != 0U } + 1) /** * Constructs [NumberedPolynomial] with provided coefficients map [coefs]. The map is used as is. */ -@Suppress("FunctionName", "NOTHING_TO_INLINE") @PublishedApi internal inline fun NumberedPolynomialAsIs(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs) @@ -25,7 +26,6 @@ internal inline fun NumberedPolynomialAsIs(coefs: Map, C>) : Numb * 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. */ -@Suppress("FunctionName", "NOTHING_TO_INLINE") @PublishedApi internal inline fun NumberedPolynomialAsIs(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs.toMap()) @@ -33,7 +33,6 @@ internal inline fun NumberedPolynomialAsIs(pairs: Collection * 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. */ -@Suppress("FunctionName", "NOTHING_TO_INLINE") @PublishedApi internal inline fun NumberedPolynomialAsIs(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(pairs.toMap()) @@ -43,7 +42,6 @@ internal inline fun NumberedPolynomialAsIs(vararg pairs: Pair, C> * **Be sure you read description of [NumberedPolynomial.coefficients]. Otherwise, you may make a mistake that will * cause wrong computation result or even runtime error.** */ -@Suppress("FunctionName", "NOTHING_TO_INLINE") @DelicatePolynomialAPI public inline fun NumberedPolynomialWithoutCheck(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs) @@ -54,7 +52,6 @@ public inline fun NumberedPolynomialWithoutCheck(coefs: Map, C>) * **Be sure you read description of [NumberedPolynomial.coefficients]. Otherwise, you may make a mistake that will * cause wrong computation result or even runtime error.** */ -@Suppress("FunctionName", "NOTHING_TO_INLINE") @DelicatePolynomialAPI public inline fun NumberedPolynomialWithoutCheck(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs.toMap()) @@ -65,7 +62,6 @@ public inline fun NumberedPolynomialWithoutCheck(pairs: Collection NumberedPolynomialWithoutCheck(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(pairs.toMap()) @@ -77,7 +73,6 @@ public inline fun NumberedPolynomialWithoutCheck(vararg pairs: Pair NumberedPolynomial(coefs: Map, C>, add: (C, C) -> C) : NumberedPolynomial { val fixedCoefs = mutableMapOf, C>() @@ -98,7 +93,6 @@ public fun NumberedPolynomial(coefs: Map, C>, add: (C, C) -> C) : * 1. Terms that happen to have the same signature will be summed up. * 1. New map will be formed of resulting terms. */ -@Suppress("FunctionName") public fun NumberedPolynomial(pairs: Collection, C>>, add: (C, C) -> C) : NumberedPolynomial { val fixedCoefs = mutableMapOf, C>() @@ -119,7 +113,6 @@ public fun NumberedPolynomial(pairs: Collection, C>>, add: ( * 1. Terms that happen to have the same signature will be summed up. * 1. New map will be formed of resulting terms. */ -@Suppress("FunctionName") public fun NumberedPolynomial(vararg pairs: Pair, C>, add: (C, C) -> C) : NumberedPolynomial { val fixedCoefs = mutableMapOf, C>() @@ -142,7 +135,6 @@ public fun NumberedPolynomial(vararg pairs: Pair, C>, add: (C, C) * 1. Terms that happen to have the same signature will be summed up. * 1. New map will be formed of resulting terms. */ -@Suppress("FunctionName", "NOTHING_TO_INLINE") public inline fun > A.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, ::add) /** * Constructs [NumberedPolynomial] with provided coefficients map [coefs]. @@ -152,7 +144,6 @@ public inline fun > A.NumberedPolynomial(coefs: Map, C> * 1. Terms that happen to have the same signature will be summed up. * 1. New map will be formed of resulting terms. */ -@Suppress("FunctionName", "NOTHING_TO_INLINE") public inline fun > NumberedPolynomialSpace.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs) { left: C, right: C -> left + right } /** @@ -163,7 +154,6 @@ public inline fun > NumberedPolynomialSpace.NumberedPolynomi * 1. Terms that happen to have the same signature will be summed up. * 1. New map will be formed of resulting terms. */ -@Suppress("FunctionName", "NOTHING_TO_INLINE") public inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs) { left: C, right: C -> left + right } /** @@ -174,7 +164,6 @@ public inline fun > NumberedRationalFunctionSpace.NumberedPo * 1. Terms that happen to have the same signature will be summed up. * 1. New map will be formed of resulting terms. */ -@Suppress("FunctionName", "NOTHING_TO_INLINE") public inline fun > A.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, ::add) /** @@ -185,7 +174,6 @@ public inline fun > A.NumberedPolynomial(pairs: Collection> 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". @@ -195,7 +183,6 @@ public inline fun > NumberedPolynomialSpace.NumberedPolynomi * 1. Terms that happen to have the same signature will be summed up. * 1. New map will be formed of resulting terms. */ -@Suppress("FunctionName", "NOTHING_TO_INLINE") public inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs) { left: C, right: C -> left + right } /** @@ -206,7 +193,6 @@ public inline fun > NumberedRationalFunctionSpace.NumberedPo * 1. Terms that happen to have the same signature will be summed up. * 1. New map will be formed of resulting terms. */ -@Suppress("FunctionName", "NOTHING_TO_INLINE") 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". @@ -216,7 +202,6 @@ public inline fun > A.NumberedPolynomial(vararg pairs: Pair> 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". @@ -226,13 +211,11 @@ public inline fun > NumberedPolynomialSpace.NumberedPolynomi * 1. Terms that happen to have the same signature will be summed up. * 1. New map will be formed of resulting terms. */ -@Suppress("FunctionName", "NOTHING_TO_INLINE") public inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs) { left: C, right: C -> left + right } /** * Converts [this] constant to [NumberedPolynomial]. */ -@Suppress("NOTHING_TO_INLINE") public inline fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomialAsIs(mapOf(emptyList() to this)) /** @@ -269,6 +252,7 @@ public class NumberedPolynomialTermSignatureBuilder { * * In fact, it just returns [signature] as regular signature of type `List`. */ + @PublishedApi internal fun build(): List = signature /** @@ -344,8 +328,7 @@ public class NumberedPolynomialBuilder( * 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) { - if (signature in coefficients) coefficients[signature] = add(coefficients[signature]!!, this@with) - else coefficients[signature] = this@with + coefficients[signature] = if (signature in coefficients) add(coefficients[signature]!!, this@with) else this@with } /** * Declares monomial with [this] coefficient and signature constructed by [block]. @@ -361,7 +344,7 @@ public class NumberedPolynomialBuilder( * 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 operator fun C.invoke(block: NumberedPolynomialTermSignatureBuilder.() -> Unit): Unit = + public inline operator fun C.invoke(block: NumberedPolynomialTermSignatureBuilder.() -> Unit): Unit = this with NumberedPolynomialTermSignatureBuilder().apply(block).build() } @@ -385,7 +368,6 @@ public class NumberedPolynomialBuilder( // 2. Union types are implemented. Then all three functions should be rewritten // as one with single union type as a (context) receiver. //@UnstableKMathAPI -//@Suppress("FunctionName") //public inline fun > A.NumberedPolynomial(initialCapacity: Int = 0, block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder(::add, initialCapacity).apply(block).build() /** * Creates [NumberedPolynomial] with lambda [block] in context of [this] ring of [NumberedPolynomial]s. @@ -401,7 +383,6 @@ public class NumberedPolynomialBuilder( * ``` */ @UnstableKMathAPI -@Suppress("FunctionName") public inline fun > NumberedPolynomialSpace.NumberedPolynomial(initialCapacity: Int = 0, block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build() /** * Creates [NumberedPolynomial] with lambda [block] in context of [this] field of [NumberedRationalFunction]s. @@ -417,7 +398,6 @@ public inline fun > NumberedPolynomialSpace.NumberedPolynomi * ``` */ @UnstableKMathAPI -@Suppress("FunctionName") public inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(initialCapacity: Int = 0, block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build() // Waiting for context receivers :( FIXME: Replace with context receivers when they will be available @@ -430,7 +410,6 @@ public inline fun > NumberedRationalFunctionSpace.NumberedPo * 1. Terms that happen to have the same signature will be summed up. * 1. New map will be formed of resulting terms. */ -@Suppress("FunctionName") public fun > A.NumberedRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): NumberedRationalFunction = NumberedRationalFunction( NumberedPolynomial(numeratorCoefficients), @@ -444,7 +423,6 @@ public fun > A.NumberedRationalFunction(numeratorCoefficients: Map * 1. Terms that happen to have the same signature will be summed up. * 1. New map will be formed of resulting terms. */ -@Suppress("FunctionName") public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): NumberedRationalFunction = NumberedRationalFunction( NumberedPolynomial(numeratorCoefficients), @@ -454,13 +432,11 @@ public fun > NumberedRationalFunctionSpace.NumberedRationalF /** * Constructs [NumberedRationalFunction] with provided [numerator] and unit denominator. */ -@Suppress("FunctionName") public fun > A.NumberedRationalFunction(numerator: NumberedPolynomial): NumberedRationalFunction = NumberedRationalFunction(numerator, NumberedPolynomial(mapOf(emptyList() to one))) /** * Constructs [NumberedRationalFunction] with provided [numerator] and unit denominator. */ -@Suppress("FunctionName") public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numerator: NumberedPolynomial): NumberedRationalFunction = NumberedRationalFunction(numerator, polynomialOne) @@ -473,7 +449,6 @@ public fun > NumberedRationalFunctionSpace.NumberedRationalF * 1. Terms that happen to have the same signature will be summed up. * 1. New map will be formed of resulting terms. */ -@Suppress("FunctionName") public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numeratorCoefficients: Map, C>): NumberedRationalFunction = NumberedRationalFunction( NumberedPolynomial(numeratorCoefficients), @@ -488,7 +463,6 @@ public fun > NumberedRationalFunctionSpace.NumberedRationalF * 1. Terms that happen to have the same signature will be summed up. * 1. New map will be formed of resulting terms. */ -@Suppress("FunctionName") public fun > A.NumberedRationalFunction(numeratorCoefficients: Map, C>): NumberedRationalFunction = NumberedRationalFunction( NumberedPolynomial(numeratorCoefficients), @@ -496,7 +470,7 @@ public fun > A.NumberedRationalFunction(numeratorCoefficients: Map ) ///** -// * Converts [this] coefficient to [NumberedRationalFunction]. +// * Converts [this] constant to [NumberedRationalFunction]. // */ //context(A) //public fun > C.asNumberedRationalFunction() : NumberedRationalFunction = @@ -505,7 +479,7 @@ public fun > A.NumberedRationalFunction(numeratorCoefficients: Map // NumberedPolynomialAsIs(mapOf(emptyList() to one)) // ) ///** -// * Converts [this] coefficient to [NumberedRationalFunction]. +// * Converts [this] constant to [NumberedRationalFunction]. // */ //context(NumberedRationalFunctionSpace) //public fun > C.asNumberedRationalFunction() : NumberedRationalFunction = diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt index fca9a8ab8..06911feca 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt @@ -51,15 +51,14 @@ public inline fun , R> A.numberedRationalFunctionSpace(block: Num */ public fun NumberedPolynomial.substitute(args: Map): NumberedPolynomial = Double.algebra { NumberedPolynomial( - buildMap, Double>(coefficients.size) { + 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()) } - if (newDegs !in this) this[newDegs] = newC - else this[newDegs] = this[newDegs]!! + newC + this[newDegs] = if (newDegs !in this) newC else this[newDegs]!! + newC } } ) @@ -70,15 +69,14 @@ public fun NumberedPolynomial.substitute(args: Map): Number */ public fun NumberedPolynomial.substitute(ring: Ring, args: Map): NumberedPolynomial = ring { NumberedPolynomial( - buildMap, C>(coefficients.size) { + 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) } - if (newDegs !in this) this[newDegs] = newC - else this[newDegs] = this[newDegs]!! + newC + this[newDegs] = if (newDegs !in this) newC else this[newDegs]!! + newC } } ) @@ -128,14 +126,14 @@ public fun NumberedRationalFunction.substitute(ring: Ring, args: Map 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 boxing + */ // TODO: To optimize calculation @JvmName("substituteRationalFunction") public fun NumberedRationalFunction.substitute(ring: Ring, args: Map>) : NumberedRationalFunction = ring.numberedRationalFunctionSpace { @@ -250,14 +248,14 @@ public fun NumberedRationalFunction.substitute(ring: Ring, args: Buffe /** * Substitutes provided arguments [args] into [this] rational function. - */ // TODO: To optimize boxing + */ // 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 boxing + */ // TODO: To optimize calculation @JvmName("substituteRationalFunction") public fun NumberedRationalFunction.substitute(ring: Ring, args: Buffer>) : NumberedRationalFunction = ring.numberedRationalFunctionSpace { -- 2.34.1 From 9fc99a4c727eb6ca5870a36a38832bddd8415aea Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sat, 25 Jun 2022 15:45:10 +0300 Subject: [PATCH 100/275] Removed extra copyright comment. --- .../space/kscience/kmath/functions/listConstructors.kt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt index 35c736914..e95361724 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt @@ -3,11 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - package space.kscience.kmath.functions import space.kscience.kmath.operations.Ring -- 2.34.1 From 403ff93f4af2960facb25696ae5fc1f50e428711 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sat, 25 Jun 2022 16:01:18 +0300 Subject: [PATCH 101/275] Moved optimizations to branch refactor/polynomials --- .../kmath/functions/listUtilOptimized.kt | 250 ------------------ .../space/kscience/kmath/functions/misc.kt | 10 - 2 files changed, 260 deletions(-) delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtilOptimized.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtilOptimized.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtilOptimized.kt deleted file mode 100644 index 6eb3a1dc7..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtilOptimized.kt +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.invoke -import kotlin.math.max -import kotlin.math.min - - -// TODO: Optimized copies of substitution and invocation -@UnstablePolynomialBoxingOptimization -@Suppress("NOTHING_TO_INLINE") -internal inline fun copyTo( - origin: List, - originDegree: Int, - target: MutableList, -) { - for (deg in 0 .. originDegree) target[deg] = origin[deg] -} - -@UnstablePolynomialBoxingOptimization -@Suppress("NOTHING_TO_INLINE") -internal inline fun multiplyAddingToUpdater( - ring: Ring, - multiplicand: MutableList, - multiplicandDegree: Int, - multiplier: List, - multiplierDegree: Int, - updater: MutableList, - zero: C, -) { - multiplyAddingTo( - ring = ring, - multiplicand = multiplicand, - multiplicandDegree = multiplicandDegree, - multiplier = multiplier, - multiplierDegree = multiplierDegree, - target = updater - ) - for (updateDeg in 0 .. multiplicandDegree + multiplierDegree) { - multiplicand[updateDeg] = updater[updateDeg] - updater[updateDeg] = zero - } -} - -@UnstablePolynomialBoxingOptimization -@Suppress("NOTHING_TO_INLINE") -internal inline fun multiplyAddingTo( - ring: Ring, - multiplicand: List, - multiplicandDegree: Int, - multiplier: List, - multiplierDegree: Int, - target: MutableList -) = ring { - for (d in 0 .. multiplicandDegree + multiplierDegree) - for (k in max(0, d - multiplierDegree)..min(multiplicandDegree, d)) - target[d] += multiplicand[k] * multiplier[d - k] -} - -@UnstablePolynomialBoxingOptimization -public fun ListPolynomial.substitute2(ring: Ring, arg: ListPolynomial) : ListPolynomial = ring { - if (coefficients.isEmpty()) return ListPolynomial(emptyList()) - - val thisDegree = coefficients.lastIndex - if (thisDegree == -1) return ListPolynomial(emptyList()) - val argDegree = arg.coefficients.lastIndex - if (argDegree == -1) return coefficients[0].asListPolynomial() - val constantZero = zero - val resultCoefs: MutableList = MutableList(thisDegree * argDegree + 1) { constantZero } - resultCoefs[0] = coefficients[thisDegree] - val resultCoefsUpdate: MutableList = MutableList(thisDegree * argDegree + 1) { constantZero } - var resultDegree = 0 - for (deg in thisDegree - 1 downTo 0) { - resultCoefsUpdate[0] = coefficients[deg] - multiplyAddingToUpdater( - ring = ring, - multiplicand = resultCoefs, - multiplicandDegree = resultDegree, - multiplier = arg.coefficients, - multiplierDegree = argDegree, - updater = resultCoefsUpdate, - zero = constantZero - ) - resultDegree += argDegree - } - - return ListPolynomial(resultCoefs) -} - -/** - * Returns numerator (polynomial) of rational function gotten by substitution rational function [arg] to the polynomial instance. - * More concrete, if [arg] is a fraction `f(x)/g(x)` and the receiving instance is `p(x)`, then - * ``` - * p(f/g) * g^deg(p) - * ``` - * is returned. - * - * Used in [ListPolynomial.substitute] and [ListRationalFunction.substitute] for performance optimisation. - */ // TODO: Дописать -@UnstablePolynomialBoxingOptimization -internal fun ListPolynomial.substituteRationalFunctionTakeNumerator(ring: Ring, arg: ListRationalFunction): ListPolynomial = ring { - if (coefficients.isEmpty()) return ListPolynomial(emptyList()) - - val thisDegree = coefficients.lastIndex - if (thisDegree == -1) return ListPolynomial(emptyList()) - val thisDegreeLog2 = 31 - thisDegree.countLeadingZeroBits() - val numeratorDegree = arg.numerator.coefficients.lastIndex - val denominatorDegree = arg.denominator.coefficients.lastIndex - val argDegree = max(numeratorDegree, denominatorDegree) - val constantZero = zero - val powersOf2 = buildList(thisDegreeLog2 + 1) { - var result = 1 - for (exp in 0 .. thisDegreeLog2) { - add(result) - result = result shl 1 - } - } - val hashes = powersOf2.runningReduce { acc, i -> acc + i } - val numeratorPowers = buildList>(thisDegreeLog2 + 1) { - add(arg.numerator.coefficients) - repeat(thisDegreeLog2) { - val next = MutableList(powersOf2[it + 1] * numeratorDegree + 1) { constantZero } - add(next) - val last = last() - multiplyAddingTo( - ring = ring, - multiplicand = last, - multiplicandDegree = powersOf2[it] * numeratorDegree + 1, - multiplier = last, - multiplierDegree = powersOf2[it] * numeratorDegree + 1, - target = next, - ) - } - } - val denominatorPowers = buildList>(thisDegreeLog2 + 1) { - add(arg.denominator.coefficients) - repeat(thisDegreeLog2) { - val next = MutableList(powersOf2[it + 1] * denominatorDegree + 1) { constantZero } - add(next) - val last = last() - multiplyAddingTo( - ring = ring, - multiplicand = last, - multiplicandDegree = powersOf2[it] * denominatorDegree + 1, - multiplier = last, - multiplierDegree = powersOf2[it] * denominatorDegree + 1, - target = next, - ) - } - } - val levelResultCoefsPool = buildList>(thisDegreeLog2 + 1) { - repeat(thisDegreeLog2 + 1) { - add(MutableList(hashes[it] * argDegree) { constantZero }) - } - } - val edgedMultiplier = MutableList(0) { TODO() } - val edgedMultiplierUpdater = MutableList(0) { TODO() } - - fun MutableList.reset() { - for (i in indices) set(i, constantZero) - } - - fun processLevel(level: Int, start: Int, end: Int) : List { - val levelResultCoefs = levelResultCoefsPool[level + 1] - - if (level == -1) { - levelResultCoefs[0] = coefficients[start] - } else { - levelResultCoefs.reset() - multiplyAddingTo( - ring = ring, - multiplicand = processLevel(level = level - 1, start = start, end = (start + end) / 2), - multiplicandDegree = hashes[level] * argDegree, - multiplier = denominatorPowers[level], - multiplierDegree = powersOf2[level] * denominatorDegree, - target = levelResultCoefs - ) - multiplyAddingTo( - ring = ring, - multiplicand = processLevel(level = level - 1, start = (start + end) / 2, end = end), - multiplicandDegree = hashes[level] * argDegree, - multiplier = numeratorPowers[level], - multiplierDegree = powersOf2[level] * numeratorDegree, - target = levelResultCoefs - ) - } - - return levelResultCoefs - } - - fun processLevelEdged(level: Int, start: Int, end: Int) : List { - val levelResultCoefs = levelResultCoefsPool[level + 1] - - if (level == -1) { - levelResultCoefs[0] = coefficients[start] - } else { - val levelsPowerOf2 = powersOf2[level] - if (end - start >= levelsPowerOf2) { - multiplyAddingTo( - ring = ring, - multiplicand = processLevelEdged(level = level - 1, start = start + levelsPowerOf2, end = end), - multiplicandDegree = hashes[level] * argDegree, // TODO: Ввести переменную - multiplier = numeratorPowers[level], - multiplierDegree = powersOf2[level] * numeratorDegree, - target = levelResultCoefs - ) - multiplyAddingTo( - ring = ring, - multiplicand = processLevel(level = level - 1, start = start, end = start + levelsPowerOf2), - multiplicandDegree = hashes[level] * argDegree, - multiplier = edgedMultiplier, - multiplierDegree = max((hashes[level] and thisDegree) - powersOf2[level] + 1, 0) * denominatorDegree, // TODO: Ввести переменную - target = levelResultCoefs - ) - if (level != thisDegreeLog2) { - multiplyAddingToUpdater( - ring = ring, - multiplicand = edgedMultiplier, - multiplicandDegree = max((hashes[level] and thisDegree) - powersOf2[level] + 1, 0) * denominatorDegree, // TODO: Ввести переменную - multiplier = denominatorPowers[level], - multiplierDegree = powersOf2[level] * denominatorDegree, - updater = edgedMultiplierUpdater, - zero = constantZero - ) - } - } else { - copyTo( - origin = processLevelEdged(level = level - 1, start = start + levelsPowerOf2, end = end), - originDegree = hashes[level] * argDegree, // TODO: Ввести переменную - target = levelResultCoefs - ) - } - } - - return levelResultCoefs - } - - return ListPolynomial( - processLevelEdged( - level = thisDegreeLog2, - start = 0, - end = thisDegree + 1 - ) - ) -} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt index 7d6fc84fa..aba246519 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt @@ -6,16 +6,6 @@ package space.kscience.kmath.functions -/** - * Marks operations that are going to be optimized reimplementations by reducing number of boxings but currently is - * under development and is not stable (or even ready to use). - */ -@RequiresOptIn( - message = "It's copy of operation with optimized boxing. It's currently unstable.", - level = RequiresOptIn.Level.ERROR -) -internal annotation class UnstablePolynomialBoxingOptimization - /** * 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 -- 2.34.1 From 3e917baaaf86ae8a7c73eda36c20dafbe418bda0 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sat, 25 Jun 2022 21:23:32 +0300 Subject: [PATCH 102/275] Added examples for polynomials. Also: - Fixed bug in differentiation of NumberedPolynomials. - Fixed bug in addition and subtraction of LabeledPolynomials. - Added references to NumberedPolynomialWithoutCheck and LabeledPolynomialWithoutCheck. - Made NumberedRationalFunction and LabeledRationalFunction classes data. Made their constructor public. --- .../kscience/kmath/functions/polynomials.kt | 396 ++++++++++++++++++ .../kmath/functions/LabeledPolynomial.kt | 4 +- .../functions/LabeledRationalFunction.kt | 2 +- .../functions/NumberedRationalFunction.kt | 2 +- .../kmath/functions/labeledConstructors.kt | 24 ++ .../kmath/functions/numberedConstructors.kt | 22 + .../kscience/kmath/functions/numberedUtil.kt | 6 +- 7 files changed, 449 insertions(+), 7 deletions(-) create mode 100644 examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt new file mode 100644 index 000000000..273fe5cb9 --- /dev/null +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt @@ -0,0 +1,396 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.expressions.symbol +import space.kscience.kmath.operations.algebra + + +/** + * 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 = NumberedPolynomial { + 3 {} + 5 { 2 inPowerOf 1u } + -7 with { 1 pow 2u; 3 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 = with(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 { + (-7) {} + 5 { 2 pow 1u } + 0 { 1 pow 2u; 3 pow 1u } + (-4) { 4 pow 4u } + } + ) // true + println( + polynomial1 + polynomial6 == NumberedPolynomial { + 10 {} + 0 { 2 pow 1u } + (-7) { 1 pow 2u; 3 pow 1u } + 4 { 4 pow 4u } + } + ) // true + println( + polynomial1 - polynomial6 == NumberedPolynomial { + (-4) {} + 10 { 2 pow 1u } + (-7) { 1 pow 2u; 3 pow 1u } + (-4) { 4 pow 4u } + } + ) // true + + polynomial1 * polynomial6 // Multiplication works too + } + + Double.algebra.numberedPolynomialSpace { + // You can even write + val x_1: NumberedPolynomial = NumberedPolynomial { 1.0 { 1 pow 1u } } + val x_2: NumberedPolynomial = NumberedPolynomial { 1.0 { 2 pow 1u } } + val x_3: NumberedPolynomial = NumberedPolynomial { 1.0 { 3 pow 1u } } + val polynomial7: NumberedPolynomial = NumberedPolynomial { + 3.0 {} + 5.0 { 2 pow 1u } + (-7.0) { 1 pow 2u; 3 pow 1u } + } + 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 { 1 { 4 pow 1u } } + // 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 { + 3 {} + 5 { 4 pow 1u } + (-7) { 1 pow 2u; 3 pow 1u } + } + ) // 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 { 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 { + 2.0 {} + (-3.0) { 1 pow 1u } + 1.0 { 1 pow 2u } + }, + NumberedPolynomial { + 3.0 {} + (-1.0) { 1 pow 1u } + } + ) + // It's just (2 - 3x + x^2)/(3 - x) where x = x_1 + + val rationalFunction2: NumberedRationalFunction = NumberedRationalFunction( + NumberedPolynomial { + 5.0 {} + (-4.0) { 1 pow 1u } + 1.0 { 1 pow 2u } + }, + NumberedPolynomial { + 3.0 {} + (-1.0) { 1 pow 1u } + } + ) + // 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 = LabeledPolynomial { + 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 = with(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 { + (-7) {} + 5 { y pow 1u } + 0 { x pow 2u; z pow 1u } + (-4) { t pow 4u } + } + ) // true + println( + polynomial1 + polynomial6 == LabeledPolynomial { + 10 {} + 0 { y pow 1u } + (-7) { x pow 2u; z pow 1u } + 4 { t pow 4u } + } + ) // true + println( + polynomial1 - polynomial6 == LabeledPolynomial { + (-4) {} + 10 { y pow 1u } + (-7) { x pow 2u; z pow 1u } + (-4) { t pow 4u } + } + ) // true + + polynomial1 * polynomial6 // Multiplication works too + } + + Double.algebra.labeledPolynomialSpace { + // You can even write + val polynomial7: LabeledPolynomial = LabeledPolynomial { + 3.0 {} + 5.0 { y pow 1u } + (-7.0) { x pow 2u; z pow 1u } + } + 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 { + 3 {} + 5 { t pow 1u } + (-7) { x pow 2u; z pow 1u } + } + ) // true, because it's substitution y -> t, so result is 3 + 5 t - 7 x^2 z + println( + polynomial1.derivativeWithRespectTo(Int.algebra, y) == LabeledPolynomial { 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 { + 2.0 {} + (-3.0) { x pow 1u } + 1.0 { x pow 2u } + }, + LabeledPolynomial { + 3.0 {} + (-1.0) { x pow 1u } + } + ) + // It's just (2 - 3x + x^2)/(3 - x) + + val rationalFunction2: LabeledRationalFunction = LabeledRationalFunction( + LabeledPolynomial { + 5.0 {} + (-4.0) { x pow 1u } + 1.0 { x pow 2u } + }, + LabeledPolynomial { + 3.0 {} + (-1.0) { x pow 1u } + } + ) + // 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-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt index b0c54502d..061325b60 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -522,7 +522,7 @@ public class LabeledPolynomialSpace>( override operator fun LabeledPolynomial.plus(other: LabeledPolynomial): LabeledPolynomial = LabeledPolynomialAsIs( buildMap(coefficients.size + other.coefficients.size) { - other.coefficients.mapValuesTo(this) { it.value } + coefficients.mapValuesTo(this) { it.value } other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value } } ) @@ -532,7 +532,7 @@ public class LabeledPolynomialSpace>( override operator fun LabeledPolynomial.minus(other: LabeledPolynomial): LabeledPolynomial = LabeledPolynomialAsIs( buildMap(coefficients.size + other.coefficients.size) { - other.coefficients.mapValuesTo(this) { it.value } + coefficients.mapValuesTo(this) { it.value } other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value } } ) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt index 03f323813..1b0bbbec8 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt @@ -13,7 +13,7 @@ import kotlin.jvm.JvmName /** * Represents multivariate rational function that stores its numerator and denominator as [LabeledPolynomial]s. */ -public class LabeledRationalFunction( +public data class LabeledRationalFunction( public override val numerator: LabeledPolynomial, public override val denominator: LabeledPolynomial ) : RationalFunction> { diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt index 92f507735..497755126 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt @@ -15,7 +15,7 @@ import kotlin.math.max /** * Represents multivariate rational function that stores its numerator and denominator as [NumberedPolynomial]s. */ -public class NumberedRationalFunction internal constructor( +public data class NumberedRationalFunction( public override val numerator: NumberedPolynomial, public override val denominator: NumberedPolynomial ) : RationalFunction> { diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt index 47325c4bb..7586b7012 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt @@ -73,6 +73,8 @@ public inline fun LabeledPolynomialWithoutCheck(vararg pairs: Pair LabeledPolynomial(coefs: Map, C>, add: (C, C) -> C) : LabeledPolynomial { val fixedCoefs = mutableMapOf, C>() @@ -93,6 +95,8 @@ public fun LabeledPolynomial(coefs: Map, C>, add: (C, C) - * 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 { val fixedCoefs = mutableMapOf, C>() @@ -113,6 +117,8 @@ public fun LabeledPolynomial(pairs: Collection, C>>, * 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 { val fixedCoefs = mutableMapOf, C>() @@ -135,6 +141,8 @@ public fun LabeledPolynomial(vararg pairs: Pair, C>, add: * 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) /** @@ -144,6 +152,8 @@ public inline fun > A.LabeledPolynomial(coefs: Map> LabeledPolynomialSpace.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs) { left: C, right: C -> left + right } @@ -154,6 +164,8 @@ public inline fun > LabeledPolynomialSpace.LabeledPolynomial * 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 } @@ -164,6 +176,8 @@ public inline fun > LabeledRationalFunctionSpace.LabeledPoly * 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) @@ -174,6 +188,8 @@ public inline fun > A.LabeledPolynomial(pairs: Collection> LabeledPolynomialSpace.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs) { left: C, right: C -> left + right } /** @@ -183,6 +199,8 @@ public inline fun > LabeledPolynomialSpace.LabeledPolynomial * 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 } @@ -193,6 +211,8 @@ public inline fun > LabeledRationalFunctionSpace.LabeledPoly * 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 } /** @@ -202,6 +222,8 @@ public inline fun > A.LabeledPolynomial(vararg pairs: Pair> LabeledPolynomialSpace.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs) { left: C, right: C -> left + right } /** @@ -211,6 +233,8 @@ public inline fun > LabeledPolynomialSpace.LabeledPolynomial * 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 } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt index 4850e6cec..3cd398623 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt @@ -72,6 +72,8 @@ public inline fun NumberedPolynomialWithoutCheck(vararg pairs: Pair NumberedPolynomial(coefs: Map, C>, add: (C, C) -> C) : NumberedPolynomial { val fixedCoefs = mutableMapOf, C>() @@ -92,6 +94,8 @@ public fun NumberedPolynomial(coefs: Map, C>, add: (C, C) -> C) : * 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 { val fixedCoefs = mutableMapOf, C>() @@ -112,6 +116,8 @@ public fun NumberedPolynomial(pairs: Collection, C>>, add: ( * 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 { val fixedCoefs = mutableMapOf, C>() @@ -134,6 +140,8 @@ public fun NumberedPolynomial(vararg pairs: Pair, C>, add: (C, C) * 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) /** @@ -143,6 +151,8 @@ public inline fun > A.NumberedPolynomial(coefs: Map, C> * 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 } @@ -153,6 +163,8 @@ public inline fun > NumberedPolynomialSpace.NumberedPolynomi * 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 } @@ -163,6 +175,8 @@ public inline fun > NumberedRationalFunctionSpace.NumberedPo * 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) @@ -173,6 +187,8 @@ public inline fun > A.NumberedPolynomial(pairs: Collection> NumberedPolynomialSpace.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs) { left: C, right: C -> left + right } /** @@ -192,6 +208,8 @@ public inline fun > NumberedRationalFunctionSpace.NumberedPo * 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 } /** @@ -201,6 +219,8 @@ public inline fun > A.NumberedPolynomial(vararg pairs: Pair> NumberedPolynomialSpace.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs) { left: C, right: C -> left + right } /** @@ -210,6 +230,8 @@ public inline fun > NumberedPolynomialSpace.NumberedPolynomi * 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 } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt index 06911feca..96f5f480b 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt @@ -353,7 +353,7 @@ public fun > NumberedPolynomial.derivativeWithRespectTo( buildMap(coefficients.size) { coefficients .forEach { (degs, c) -> - if (degs.size > variable) return@forEach + if (degs.lastIndex < variable) return@forEach put( degs.mapIndexed { index, deg -> when { @@ -383,7 +383,7 @@ public fun > NumberedPolynomial.nthDerivativeWithRespectTo( buildMap(coefficients.size) { coefficients .forEach { (degs, c) -> - if (degs.size > variable) return@forEach + if (degs.lastIndex < variable) return@forEach put( degs.mapIndexed { index, deg -> when { @@ -417,7 +417,7 @@ public fun > NumberedPolynomial.nthDerivativeWithRespectTo( buildMap(coefficients.size) { coefficients .forEach { (degs, c) -> - if (degs.size > maxRespectedVariable) return@forEach + if (degs.lastIndex < maxRespectedVariable) return@forEach put( degs.mapIndexed { index, deg -> if (index !in filteredVariablesAndOrders) return@mapIndexed deg -- 2.34.1 From 630d16bbeefbd8d402732dd8410ea950c26a6ca6 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sun, 26 Jun 2022 12:16:51 +0300 Subject: [PATCH 103/275] Added design notes. Also: - Changed `xxxPolynomialSpace()` and `xxxPolynomialSpace()` functions to `xxxPolynomialSpace` value properties. - Changed inconsistency of names `XxxRationalFunctionalSpaceYyy` and `XxxRationalFunctionSpaceYyy` in favor of second one. --- docs/polynomials.md | 172 ++++++++++++++++++ .../functions/LabeledRationalFunction.kt | 2 +- .../kmath/functions/ListRationalFunction.kt | 2 +- .../functions/NumberedRationalFunction.kt | 2 +- .../kmath/functions/RationalFunction.kt | 22 +-- .../kscience/kmath/functions/labeledUtil.kt | 8 +- .../kscience/kmath/functions/listUtil.kt | 12 +- .../kscience/kmath/functions/numberedUtil.kt | 8 +- 8 files changed, 200 insertions(+), 28 deletions(-) create mode 100644 docs/polynomials.md diff --git a/docs/polynomials.md b/docs/polynomials.md new file mode 100644 index 000000000..fe69948e5 --- /dev/null +++ b/docs/polynomials.md @@ -0,0 +1,172 @@ +# Polynomials and Rational Functions + +KMath provides a way to work with uni- and multivariate polynomials and rational functions. It includes full support of arithmetic operations of integers, **constants** (elements of ring polynomials are build over), variables (for certain multivariate implementations), polynomials and rational functions encapsulated in so-called **polynomial space** and **rational function space** and some other utilities such as algebraic differentiation and substitution. + +## Concrete realizations + +There are 3 approaches to represent polynomials: +1. For univariate polynomials one can represent and store polynomial as a list of coefficients for each power of the variable. I.e. polynomial $a_0 + \dots + a_n x^n $ can be represented as a finite sequence $(a_0; \dots; a_n)$. (Compare to sequential definition of polynomials.) +2. For multivariate polynomials one can represent and store polynomial as a matching (in programming it is called "map" or "dictionary", in math it is called [functional relation](https://en.wikipedia.org/wiki/Binary_relation#Special_types_of_binary_relations)) of each "**term signature**" (that describes what variables and in what powers appear in the term) with corresponding coefficient of the term. But there are 2 possible approaches of term signature representation: + 1. One can number all the variables, so term signature can be represented as a sequence describing powers of the variables. I.e. signature of term $c \\; x_0^{d_0} \dots x_n^{d_n} $ (for natural or zero $d_i $) can be represented as a finite sequence $(d_0; \dots; d_n)$. + 2. One can represent variables as objects ("**labels**"), so term signature can be also represented as a matching of each appeared variable with its power in the term. + +All that three approaches are implemented by "list", "numbered", and "labeled" versions of polynomials and polynomial spaces respectively. Whereas all rational functions are represented as fractions with corresponding polynomial numerator and denominator, and rational functions' spaces are implemented in the same way as usual field of rational numbers (or more precisely, as any field of fractions over integral domain) should be implemented. + +So here are a bit of details. Let `C` by type of constants. Then: +1. `ListPolynomial`, `ListPolynomialSpace`, `ListRationalFunction` and `ListRationalFunctionSpace` implement the first scenario. `ListPolynomial` stores polynomial $a_0 + \dots + a_n x^n $ as a coefficients list `listOf(a_0, ..., a_n)` (of type `List`). + + They also have variation `ScalableListPolynomialSpace` that replaces former polynomials and implements `ScaleOperations`. +2. `NumberedPolynomial`, `NumberedPolynomialSpace`, `NumberedRationalFunction` and `NumberedRationalFunctionSpace` implement second scenario. `NumberedPolynomial` stores polynomials as structures of type `Map, C>`. Signatures are stored as `List`. To prevent ambiguity signatures should not end with zeros. +3. `LabeledPolynomial`, `LabeledPolynomialSpace`, `LabeledRationalFunction` and `LabeledRationalFunctionSpace` implement third scenario using common `Symbol` as variable type. `LabeledPolynomial` stores polynomials as structures of type `Map, C>`. Signatures are stored as `Map`. To prevent ambiguity each signature should not map any variable to zero. + +### Example: `ListPolynomial` + +For example, polynomial $2 - 3x + x^2 $ (with `Int` coefficients) is represented +```kotlin +val polynomial: ListPolynomial = ListPolynomial(listOf(2, -3, 1)) +// or +val polynomial: ListPolynomial = ListPolynomial(2, -3, 1) +``` + +All algebraic operations can be used in corresponding space: +```kotlin +val computationResult = Int.algebra.listPolynomialSpace { + ListPolynomial(2, -3, 1) + ListPolynomial(0, 6) == ListPolynomial(2, 3, 1) +} + +println(computationResult) // true +``` + +For more see [examples](../examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt). + +### Example: `NumberedPolynomial` + +For example, polynomial $3 + 5 x_1 - 7 x_0^2 x_2 $ (with `Int` coefficients) is represented +```kotlin +val polynomial: NumberedPolynomial = NumberedPolynomial( + mapOf( + listOf() to 3, + listOf(0u, 1u) to 5, + listOf(2u, 0u, 1u) to -7, + ) +) +// or +val polynomial: NumberedPolynomial = NumberedPolynomial( + listOf() to 3, + listOf(0u, 1u) to 5, + listOf(2u, 0u, 1u) to -7, +) +``` + +All algebraic operations can be used in corresponding space: +```kotlin +val computationResult = Int.algebra.numberedPolynomialSpace { + NumberedPolynomial( + listOf() to 3, + listOf(0u, 1u) to 5, + listOf(2u, 0u, 1u) to -7, + ) + NumberedPolynomial( + listOf(0u, 1u) to -5, + listOf(0u, 0u, 0u, 4u) to 4, + ) == NumberedPolynomial( + listOf() to 3, + listOf(0u, 1u) to 0, + listOf(2u, 0u, 1u) to -7, + listOf(0u, 0u, 0u, 4u) to 4, + ) +} + +println(computationResult) // true +``` + +For more see [examples](../examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt). + +### Example: `LabeledPolynomial` + +For example, polynomial $3 + 5 y - 7 x^2 z $ (with `Int` coefficients) is represented +```kotlin +val polynomial: LabeledPolynomial = LabeledPolynomial( + mapOf( + mapOf() to 3, + mapOf(y to 1u) to 5, + mapOf(x to 2u, z to 1u) to -7, + ) +) +// or +val polynomial: LabeledPolynomial = LabeledPolynomial( + mapOf() to 3, + mapOf(y to 1u) to 5, + mapOf(x to 2u, z to 1u) to -7, +) +``` + +All algebraic operations can be used in corresponding space: +```kotlin +val computationResult = Int.algebra.labeledPolynomialSpace { + LabeledPolynomial( + listOf() to 3, + listOf(0u, 1u) to 5, + listOf(2u, 0u, 1u) to -7, + ) + LabeledPolynomial( + listOf(0u, 1u) to -5, + listOf(0u, 0u, 0u, 4u) to 4, + ) == LabeledPolynomial( + listOf() to 3, + listOf(0u, 1u) to 0, + listOf(2u, 0u, 1u) to -7, + listOf(0u, 0u, 0u, 4u) to 4, + ) +} + +println(computationResult) // true +``` + +For more see [examples](../examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt). + +## Abstract entities (interfaces and abstract classes) + +```mermaid +classDiagram + Polynomial <|-- ListPolynomial + Polynomial <|-- NumberedPolynomial + Polynomial <|-- LabeledPolynomial + + RationalFunction <|-- ListRationalFunction + RationalFunction <|-- NumberedRationalFunction + RationalFunction <|-- LabeledRationalFunction + + Ring <|-- PolynomialSpace + PolynomialSpace <|-- MultivariatePolynomialSpace + PolynomialSpace <|-- PolynomialSpaceOverRing + + Ring <|-- RationalFunctionSpace + RationalFunctionSpace <|-- MultivariateRationalFunctionSpace + RationalFunctionSpace <|-- RationalFunctionSpaceOverRing + RationalFunctionSpace <|-- RationalFunctionSpaceOverPolynomialSpace + RationalFunctionSpace <|-- PolynomialSpaceOfFractions + RationalFunctionSpaceOverPolynomialSpace <|-- MultivariateRationalFunctionSpaceOverMultivariatePolynomialSpace + MultivariateRationalFunctionSpace <|-- MultivariateRationalFunctionSpaceOverMultivariatePolynomialSpace + MultivariateRationalFunctionSpace <|-- MultivariatePolynomialSpaceOfFractions + PolynomialSpaceOfFractions <|-- MultivariatePolynomialSpaceOfFractions +``` + +There are implemented `Polynomial` and `RationalFunction` interfaces as abstractions of polynomials and rational functions respectively (although, there is not a lot of logic in them) and `PolynomialSpace` and `RationalFunctionSpace` (that implement `Ring` interface) as abstractions of polynomials' and rational functions' spaces respectively. More precisely, that means they allow to declare common logic of interaction with such objects and spaces: +- `Polynomial` does not provide any logic. It is marker interface. +- `RationalFunction` provides numerator and denominator of rational function and destructuring declaration for them. +- `PolynomialSpace` provides all possible arithmetic interactions of integers, constants (of type `C`), and polynomials (of type `P`) like addition, subtraction, multiplication, and some others and common properties like degree of polynomial. +- `RationalFunctionSpace` provides the same as `PolynomialSpace` but also for rational functions: all possible arithmetic interactions of integers, constants (of type `C`), polynomials (of type `P`), and rational functions (of type `R`) like addition, subtraction, multiplication, division (in some cases), and some others and common properties like degree of polynomial. + +Then to add abstraction of similar behaviour with variables (in multivariate case) there are implemented `MultivariatePolynomialSpace` and `MultivariateRationalFunctionSpace`. They just include variables (of type `V`) in the interactions of the entities. + +Also, to remove boilerplates there were provided helping subinterfaces and abstract subclasses: +- `PolynomialSpaceOverRing` allows to replace implementation of interactions of integers and constants with implementations from provided ring over constants (of type `A: Ring`). +- `RationalFunctionSpaceOverRing` — the same but for `RationalFunctionSpace`. +- `RationalFunctionSpaceOverPolynomialSpace` — the same but "the inheritance" includes interactions with polynomials from provided `PolynomialSpace`. +- `PolynomialSpaceOfFractions` is actually abstract subclass of `RationalFunctionSpace` that implements all fractions boilerplates with provided (`protected`) constructor of rational functions by polynomial numerator and denominator. +- `MultivariateRationalFunctionSpaceOverMultivariatePolynomialSpace` and `MultivariatePolynomialSpaceOfFractions` — the same stories of operators inheritance and fractions boilerplates respectively but in multivariate case. + +## Utilities + +For all kinds of polynomials there are provided (implementation details depend on kind of polynomials) such common utilities as: +1. differentiation and anti-differentiation, +2. substitution, invocation and functional representation. \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt index 1b0bbbec8..b1d0dd4d9 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt @@ -30,7 +30,7 @@ public data class LabeledRationalFunction( public class LabeledRationalFunctionSpace>( public val ring: A, ) : - MultivariateRationalFunctionalSpaceOverMultivariatePolynomialSpace< + MultivariateRationalFunctionSpaceOverMultivariatePolynomialSpace< C, Symbol, LabeledPolynomial, diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt index e23baa548..7434063f2 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt @@ -28,7 +28,7 @@ public data class ListRationalFunction( public class ListRationalFunctionSpace> ( public val ring: A, ) : - RationalFunctionalSpaceOverPolynomialSpace< + RationalFunctionSpaceOverPolynomialSpace< C, ListPolynomial, ListRationalFunction, diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt index 497755126..e61d6c55e 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt @@ -32,7 +32,7 @@ public data class NumberedRationalFunction( public class NumberedRationalFunctionSpace> ( public val ring: A, ) : - RationalFunctionalSpaceOverPolynomialSpace< + RationalFunctionSpaceOverPolynomialSpace< C, NumberedPolynomial, NumberedRationalFunction, diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index 338ae9935..1782dba74 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -29,7 +29,7 @@ public interface RationalFunction> { * @param R the type of rational functions. */ @Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") // FIXME: Waiting for KT-31420 -public interface RationalFunctionalSpace, R: RationalFunction> : Ring { +public interface RationalFunctionSpace, R: RationalFunction> : Ring { /** * Returns sum of the constant and the integer represented as a constant (member of underlying ring). * @@ -459,12 +459,12 @@ public interface RationalFunctionalSpace, R: RationalFunctio * @param A the type of algebraic structure (precisely, of ring) provided for constants. */ @Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 -public interface RationalFunctionalSpaceOverRing< +public interface RationalFunctionSpaceOverRing< C, P: Polynomial, R: RationalFunction, A: Ring - > : RationalFunctionalSpace { + > : RationalFunctionSpace { /** * Underlying ring of constants. Its operations on constants are inherited by local operations on constants. @@ -561,12 +561,12 @@ public interface RationalFunctionalSpaceOverRing< * @param AP the type of algebraic structure (precisely, of ring) provided for polynomials. */ @Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 -public interface RationalFunctionalSpaceOverPolynomialSpace< +public interface RationalFunctionSpaceOverPolynomialSpace< C, P: Polynomial, R: RationalFunction, AP: PolynomialSpace, - > : RationalFunctionalSpace { + > : RationalFunctionSpace { /** * Underlying polynomial ring. Its polynomial operations are inherited by local polynomial operations. @@ -797,7 +797,7 @@ public abstract class PolynomialSpaceOfFractions< C, P: Polynomial, R: RationalFunction, - > : RationalFunctionalSpace { + > : RationalFunctionSpace { /** * Constructor of rational functions (of type [R]) from numerator and denominator (of type [P]). @@ -1106,12 +1106,12 @@ public abstract class PolynomialSpaceOfFractions< * @param R the type of rational functions. */ @Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 -public interface MultivariateRationalFunctionalSpace< +public interface MultivariateRationalFunctionSpace< C, V, P: Polynomial, R: RationalFunction - >: RationalFunctionalSpace { + >: RationalFunctionSpace { /** * Returns sum of the variable represented as a monic monomial and the integer represented as a constant polynomial. */ @@ -1335,13 +1335,13 @@ public interface MultivariateRationalFunctionalSpace< * @param AP the type of algebraic structure (precisely, of ring) provided for polynomials. */ @Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 -public interface MultivariateRationalFunctionalSpaceOverMultivariatePolynomialSpace< +public interface MultivariateRationalFunctionSpaceOverMultivariatePolynomialSpace< C, V, P: Polynomial, R: RationalFunction, AP: MultivariatePolynomialSpace, - > : RationalFunctionalSpaceOverPolynomialSpace, MultivariateRationalFunctionalSpace { + > : RationalFunctionSpaceOverPolynomialSpace, MultivariateRationalFunctionSpace { /** * Returns sum of the variable represented as a monic monomial and the integer represented as a constant polynomial. */ @@ -1517,7 +1517,7 @@ public abstract class MultivariatePolynomialSpaceOfFractions< V, P: Polynomial, R: RationalFunction, - > : MultivariateRationalFunctionalSpace, PolynomialSpaceOfFractions() { + > : MultivariateRationalFunctionSpace, PolynomialSpaceOfFractions() { /** * Returns sum of the variable represented as a rational function and the rational function. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt index 39c781a14..4002eb25a 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt @@ -19,8 +19,8 @@ import kotlin.jvm.JvmName /** * Creates a [LabeledPolynomialSpace] over a received ring. */ -public fun > A.labeledPolynomialSpace(): LabeledPolynomialSpace = - LabeledPolynomialSpace(this) +public inline val > A.labeledPolynomialSpace: LabeledPolynomialSpace + get() = LabeledPolynomialSpace(this) /** * Creates a [LabeledPolynomialSpace]'s scope over a received ring. @@ -32,8 +32,8 @@ public inline fun , R> A.labeledPolynomialSpace(block: LabeledPol /** * Creates a [LabeledRationalFunctionSpace] over a received ring. */ -public fun > A.labeledRationalFunctionSpace(): LabeledRationalFunctionSpace = - LabeledRationalFunctionSpace(this) +public inline val > A.labeledRationalFunctionSpace: LabeledRationalFunctionSpace + get() = LabeledRationalFunctionSpace(this) /** * Creates a [LabeledRationalFunctionSpace]'s scope over a received ring. diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt index 649fc48bd..4f3f6d88e 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt @@ -16,8 +16,8 @@ import kotlin.math.pow /** * Creates a [ListPolynomialSpace] over a received ring. */ -public fun > A.listPolynomialSpace(): ListPolynomialSpace = - ListPolynomialSpace(this) +public inline val > A.listPolynomialSpace: ListPolynomialSpace + get() = ListPolynomialSpace(this) /** * Creates a [ListPolynomialSpace]'s scope over a received ring. @@ -30,8 +30,8 @@ public inline fun , R> A.listPolynomialSpace(block: ListPolynomia /** * Creates a [ScalableListPolynomialSpace] over a received scalable ring. */ -public fun A.scalableListPolynomialSpace(): ScalableListPolynomialSpace where A : Ring, A : ScaleOperations = - ScalableListPolynomialSpace(this) +public inline val A.scalableListPolynomialSpace: ScalableListPolynomialSpace where A : Ring, A : ScaleOperations + get() = ScalableListPolynomialSpace(this) /** * Creates a [ScalableListPolynomialSpace]'s scope over a received scalable ring. @@ -44,8 +44,8 @@ public inline fun A.scalableListPolynomialSpace(block: ScalableListPol /** * Creates a [ListRationalFunctionSpace] over a received ring. */ -public fun > A.listRationalFunctionSpace(): ListRationalFunctionSpace = - ListRationalFunctionSpace(this) +public inline val > A.listRationalFunctionSpace: ListRationalFunctionSpace + get() = ListRationalFunctionSpace(this) /** * Creates a [ListRationalFunctionSpace]'s scope over a received ring. diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt index 96f5f480b..e485652f4 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt @@ -21,8 +21,8 @@ import kotlin.math.min /** * Creates a [NumberedPolynomialSpace] over a received ring. */ -public fun > A.numberedPolynomialSpace(): NumberedPolynomialSpace = - NumberedPolynomialSpace(this) +public inline val > A.numberedPolynomialSpace: NumberedPolynomialSpace + get() = NumberedPolynomialSpace(this) /** * Creates a [NumberedPolynomialSpace]'s scope over a received ring. @@ -35,8 +35,8 @@ public inline fun , R> A.numberedPolynomialSpace(block: NumberedP /** * Creates a [NumberedRationalFunctionSpace] over a received ring. */ -public fun > A.numberedRationalFunctionSpace(): NumberedRationalFunctionSpace = - NumberedRationalFunctionSpace(this) +public inline val > A.numberedRationalFunctionSpace: NumberedRationalFunctionSpace + get() = NumberedRationalFunctionSpace(this) /** * Creates a [NumberedRationalFunctionSpace]'s scope over a received ring. -- 2.34.1 From cb7291ccb00e5b167b69928360ae4fadafcaf0cd Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sun, 26 Jun 2022 12:58:30 +0300 Subject: [PATCH 104/275] Little addition to polynomials design note. --- docs/polynomials.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/polynomials.md b/docs/polynomials.md index fe69948e5..b255acda1 100644 --- a/docs/polynomials.md +++ b/docs/polynomials.md @@ -8,7 +8,7 @@ There are 3 approaches to represent polynomials: 1. For univariate polynomials one can represent and store polynomial as a list of coefficients for each power of the variable. I.e. polynomial $a_0 + \dots + a_n x^n $ can be represented as a finite sequence $(a_0; \dots; a_n)$. (Compare to sequential definition of polynomials.) 2. For multivariate polynomials one can represent and store polynomial as a matching (in programming it is called "map" or "dictionary", in math it is called [functional relation](https://en.wikipedia.org/wiki/Binary_relation#Special_types_of_binary_relations)) of each "**term signature**" (that describes what variables and in what powers appear in the term) with corresponding coefficient of the term. But there are 2 possible approaches of term signature representation: 1. One can number all the variables, so term signature can be represented as a sequence describing powers of the variables. I.e. signature of term $c \\; x_0^{d_0} \dots x_n^{d_n} $ (for natural or zero $d_i $) can be represented as a finite sequence $(d_0; \dots; d_n)$. - 2. One can represent variables as objects ("**labels**"), so term signature can be also represented as a matching of each appeared variable with its power in the term. + 2. One can represent variables as objects ("**labels**"), so term signature can be also represented as a matching of each appeared variable with its power in the term. I.e. signature of term $c \\; x_0^{d_0} \dots x_n^{d_n} $ (for natural non-zero $d_i $) can be represented as a finite matching $(x_0 \to d_1; \dots; x_n \to d_n)$. All that three approaches are implemented by "list", "numbered", and "labeled" versions of polynomials and polynomial spaces respectively. Whereas all rational functions are represented as fractions with corresponding polynomial numerator and denominator, and rational functions' spaces are implemented in the same way as usual field of rational numbers (or more precisely, as any field of fractions over integral domain) should be implemented. -- 2.34.1 From ed634013f67b71002919ef43a75555f1623d1945 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Mon, 27 Jun 2022 17:07:33 +0300 Subject: [PATCH 105/275] Removed extra suppresses. --- .../kmath/functions/LabeledPolynomial.kt | 2 -- .../functions/LabeledRationalFunction.kt | 6 ----- .../kmath/functions/ListPolynomial.kt | 7 ------ .../kmath/functions/ListRationalFunction.kt | 16 ------------- .../functions/NumberedRationalFunction.kt | 24 ------------------- .../kmath/functions/labeledConstructors.kt | 6 +---- .../kmath/functions/numberedConstructors.kt | 6 +---- 7 files changed, 2 insertions(+), 65 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt index 061325b60..f1859ac4b 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -610,12 +610,10 @@ public class LabeledPolynomialSpace>( /** * Substitutes provided arguments [arguments] into [this] polynomial. */ - @Suppress("NOTHING_TO_INLINE") public inline fun LabeledPolynomial.substitute(arguments: Map): LabeledPolynomial = substitute(ring, arguments) /** * Substitutes provided arguments [arguments] into [this] polynomial. */ - @Suppress("NOTHING_TO_INLINE") @JvmName("substitutePolynomial") public inline fun LabeledPolynomial.substitute(arguments: Map>) : LabeledPolynomial = substitute(ring, arguments) } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt index b1d0dd4d9..c34d1e46f 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt @@ -62,35 +62,29 @@ public class LabeledRationalFunctionSpace>( /** * Substitutes provided constant [argument] into [this] polynomial. */ - @Suppress("NOTHING_TO_INLINE") public inline fun LabeledPolynomial.substitute(argument: Map): LabeledPolynomial = substitute(ring, argument) /** * Substitutes provided polynomial [argument] into [this] polynomial. */ - @Suppress("NOTHING_TO_INLINE") @JvmName("substitutePolynomial") public inline fun LabeledPolynomial.substitute(argument: Map>): LabeledPolynomial = substitute(ring, argument) /** * Substitutes provided rational function [argument] into [this] polynomial. */ - @Suppress("NOTHING_TO_INLINE") @JvmName("substituteRationalFunction") public inline fun LabeledPolynomial.substitute(argument: Map>): LabeledRationalFunction = substitute(ring, argument) /** * Substitutes provided constant [argument] into [this] rational function. */ - @Suppress("NOTHING_TO_INLINE") public inline fun LabeledRationalFunction.substitute(argument: Map): LabeledRationalFunction = substitute(ring, argument) /** * Substitutes provided polynomial [argument] into [this] rational function. */ - @Suppress("NOTHING_TO_INLINE") @JvmName("substitutePolynomial") public inline fun LabeledRationalFunction.substitute(argument: Map>): LabeledRationalFunction = substitute(ring, argument) /** * Substitutes provided rational function [argument] into [this] rational function. */ - @Suppress("NOTHING_TO_INLINE") @JvmName("substituteRationalFunction") public inline fun LabeledRationalFunction.substitute(argument: Map>): LabeledRationalFunction = substitute(ring, argument) } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt index 8db93cbb1..3f470d5e7 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt @@ -346,39 +346,32 @@ public open class ListPolynomialSpace>( /** * Evaluates value of [this] polynomial on provided [argument]. */ - @Suppress("NOTHING_TO_INLINE") public inline fun ListPolynomial.substitute(argument: C): C = substitute(ring, argument) /** * Substitutes provided polynomial [argument] into [this] polynomial. */ - @Suppress("NOTHING_TO_INLINE") public inline fun ListPolynomial.substitute(argument: ListPolynomial): ListPolynomial = substitute(ring, argument) /** * Represent [this] polynomial as a regular context-less function. */ - @Suppress("NOTHING_TO_INLINE") public inline fun ListPolynomial.asFunction(): (C) -> C = asFunctionOver(ring) /** * Represent [this] polynomial as a regular context-less function. */ - @Suppress("NOTHING_TO_INLINE") public inline fun ListPolynomial.asFunctionOfConstant(): (C) -> C = asFunctionOfConstantOver(ring) /** * Represent [this] polynomial as a regular context-less function. */ - @Suppress("NOTHING_TO_INLINE") public inline fun ListPolynomial.asFunctionOfPolynomial(): (ListPolynomial) -> ListPolynomial = asFunctionOfPolynomialOver(ring) /** * Evaluates value of [this] polynomial on provided [argument]. */ - @Suppress("NOTHING_TO_INLINE") public inline operator fun ListPolynomial.invoke(argument: C): C = substitute(ring, argument) /** * Evaluates value of [this] polynomial on provided [argument]. */ - @Suppress("NOTHING_TO_INLINE") public inline operator fun ListPolynomial.invoke(argument: ListPolynomial): ListPolynomial = substitute(ring, argument) } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt index 7434063f2..40c6745d9 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt @@ -55,83 +55,67 @@ public class ListRationalFunctionSpace> ( /** * Evaluates value of [this] polynomial on provided argument. */ - @Suppress("NOTHING_TO_INLINE") public inline fun ListPolynomial.substitute(argument: C): C = substitute(ring, argument) /** * Substitutes provided polynomial [argument] into [this] polynomial. */ - @Suppress("NOTHING_TO_INLINE") public inline fun ListPolynomial.substitute(argument: ListPolynomial): ListPolynomial = substitute(ring, argument) /** * Substitutes provided rational function [argument] into [this] polynomial. */ - @Suppress("NOTHING_TO_INLINE") public inline fun ListPolynomial.substitute(argument: ListRationalFunction): ListRationalFunction = substitute(ring, argument) /** * Substitutes provided polynomial [argument] into [this] rational function. */ - @Suppress("NOTHING_TO_INLINE") public inline fun ListRationalFunction.substitute(argument: ListPolynomial): ListRationalFunction = substitute(ring, argument) /** * Substitutes provided rational function [argument] into [this] rational function. */ - @Suppress("NOTHING_TO_INLINE") public inline fun ListRationalFunction.substitute(argument: ListRationalFunction): ListRationalFunction = substitute(ring, argument) /** * Represent [this] polynomial as a regular context-less function. */ - @Suppress("NOTHING_TO_INLINE") public inline fun ListPolynomial.asFunction(): (C) -> C = { substitute(ring, it) } /** * Represent [this] polynomial as a regular context-less function. */ - @Suppress("NOTHING_TO_INLINE") public inline fun ListPolynomial.asFunctionOfConstant(): (C) -> C = { substitute(ring, it) } /** * Represent [this] polynomial as a regular context-less function. */ - @Suppress("NOTHING_TO_INLINE") public inline fun ListPolynomial.asFunctionOfPolynomial(): (ListPolynomial) -> ListPolynomial = { substitute(ring, it) } /** * Represent [this] polynomial as a regular context-less function. */ - @Suppress("NOTHING_TO_INLINE") public inline fun ListPolynomial.asFunctionOfRationalFunction(): (ListRationalFunction) -> ListRationalFunction = { substitute(ring, it) } /** * Represent [this] rational function as a regular context-less function. */ - @Suppress("NOTHING_TO_INLINE") public inline fun ListRationalFunction.asFunctionOfPolynomial(): (ListPolynomial) -> ListRationalFunction = { substitute(ring, it) } /** * Represent [this] rational function as a regular context-less function. */ - @Suppress("NOTHING_TO_INLINE") public inline fun ListRationalFunction.asFunctionOfRationalFunction(): (ListRationalFunction) -> ListRationalFunction = { substitute(ring, it) } /** * Evaluates value of [this] polynomial on provided argument. */ - @Suppress("NOTHING_TO_INLINE") public inline operator fun ListPolynomial.invoke(argument: C): C = substitute(ring, argument) /** * Evaluates value of [this] polynomial on provided argument. */ - @Suppress("NOTHING_TO_INLINE") public inline operator fun ListPolynomial.invoke(argument: ListPolynomial): ListPolynomial = substitute(ring, argument) /** * Evaluates value of [this] polynomial on provided argument. */ - @Suppress("NOTHING_TO_INLINE") public inline operator fun ListPolynomial.invoke(argument: ListRationalFunction): ListRationalFunction = substitute(ring, argument) /** * Evaluates value of [this] rational function on provided argument. */ - @Suppress("NOTHING_TO_INLINE") public inline operator fun ListRationalFunction.invoke(argument: ListPolynomial): ListRationalFunction = substitute(ring, argument) /** * Evaluates value of [this] rational function on provided argument. */ - @Suppress("NOTHING_TO_INLINE") public inline operator fun ListRationalFunction.invoke(argument: ListRationalFunction): ListRationalFunction = substitute(ring, argument) } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt index e61d6c55e..97dffebe1 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt @@ -113,135 +113,111 @@ public class NumberedRationalFunctionSpace> ( /** * Substitutes provided constant [argument] into [this] polynomial. */ - @Suppress("NOTHING_TO_INLINE") public inline fun NumberedPolynomial.substitute(argument: Map): NumberedPolynomial = substitute(ring, argument) /** * Substitutes provided polynomial [argument] into [this] polynomial. */ - @Suppress("NOTHING_TO_INLINE") @JvmName("substitutePolynomial") public inline fun NumberedPolynomial.substitute(argument: Map>): NumberedPolynomial = substitute(ring, argument) /** * Substitutes provided rational function [argument] into [this] polynomial. */ - @Suppress("NOTHING_TO_INLINE") @JvmName("substituteRationalFunction") public inline fun NumberedPolynomial.substitute(argument: Map>): NumberedRationalFunction = substitute(ring, argument) /** * Substitutes provided constant [argument] into [this] rational function. */ - @Suppress("NOTHING_TO_INLINE") public inline fun NumberedRationalFunction.substitute(argument: Map): NumberedRationalFunction = substitute(ring, argument) /** * Substitutes provided polynomial [argument] into [this] rational function. */ - @Suppress("NOTHING_TO_INLINE") @JvmName("substitutePolynomial") public inline fun NumberedRationalFunction.substitute(argument: Map>): NumberedRationalFunction = substitute(ring, argument) /** * Substitutes provided rational function [argument] into [this] rational function. */ - @Suppress("NOTHING_TO_INLINE") @JvmName("substituteRationalFunction") public inline fun NumberedRationalFunction.substitute(argument: Map>): NumberedRationalFunction = substitute(ring, argument) /** * Substitutes provided constant [argument] into [this] polynomial. */ - @Suppress("NOTHING_TO_INLINE") public inline fun NumberedPolynomial.substitute(argument: Buffer): NumberedPolynomial = substitute(ring, argument) /** * Substitutes provided polynomial [argument] into [this] polynomial. */ - @Suppress("NOTHING_TO_INLINE") @JvmName("substitutePolynomial") public inline fun NumberedPolynomial.substitute(argument: Buffer>): NumberedPolynomial = substitute(ring, argument) /** * Substitutes provided rational function [argument] into [this] polynomial. */ - @Suppress("NOTHING_TO_INLINE") @JvmName("substituteRationalFunction") public inline fun NumberedPolynomial.substitute(argument: Buffer>): NumberedRationalFunction = substitute(ring, argument) /** * Substitutes provided constant [argument] into [this] rational function. */ - @Suppress("NOTHING_TO_INLINE") public inline fun NumberedRationalFunction.substitute(argument: Buffer): NumberedRationalFunction = substitute(ring, argument) /** * Substitutes provided polynomial [arguments] into [this] rational function. */ - @Suppress("NOTHING_TO_INLINE") @JvmName("substitutePolynomial") public inline fun NumberedRationalFunction.substitute(arguments: Buffer>): NumberedRationalFunction = substitute(ring, arguments) /** * Substitutes provided rational function [arguments] into [this] rational function. */ - @Suppress("NOTHING_TO_INLINE") @JvmName("substituteRationalFunction") public inline fun NumberedRationalFunction.substitute(arguments: Buffer>): NumberedRationalFunction = substitute(ring, arguments) /** * Substitutes provided constant [arguments] into [this] polynomial. */ - @Suppress("NOTHING_TO_INLINE") public inline fun NumberedPolynomial.substituteFully(arguments: Buffer): C = substituteFully(ring, arguments) /** * Represent [this] polynomial as a regular context-less function. */ - @Suppress("NOTHING_TO_INLINE") public inline fun NumberedPolynomial.asFunction(): (Buffer) -> C = asFunctionOver(ring) /** * Represent [this] polynomial as a regular context-less function. */ - @Suppress("NOTHING_TO_INLINE") public inline fun NumberedPolynomial.asFunctionOfConstant(): (Buffer) -> C = asFunctionOfConstantOver(ring) /** * Represent [this] polynomial as a regular context-less function. */ - @Suppress("NOTHING_TO_INLINE") public inline fun NumberedPolynomial.asFunctionOfPolynomial(): (Buffer>) -> NumberedPolynomial = asFunctionOfPolynomialOver(ring) /** * Represent [this] polynomial as a regular context-less function. */ - @Suppress("NOTHING_TO_INLINE") public inline fun NumberedPolynomial.asFunctionOfRationalFunction(): (Buffer>) -> NumberedRationalFunction = asFunctionOfRationalFunctionOver(ring) /** * Represent [this] polynomial as a regular context-less function. */ - @Suppress("NOTHING_TO_INLINE") public inline fun NumberedRationalFunction.asFunctionOfPolynomial(): (Buffer>) -> NumberedRationalFunction = asFunctionOfPolynomialOver(ring) /** * Represent [this] polynomial as a regular context-less function. */ - @Suppress("NOTHING_TO_INLINE") public inline fun NumberedRationalFunction.asFunctionOfRationalFunction(): (Buffer>) -> NumberedRationalFunction = asFunctionOfRationalFunctionOver(ring) /** * Evaluates value of [this] polynomial on provided [arguments]. */ - @Suppress("NOTHING_TO_INLINE") public inline operator fun NumberedPolynomial.invoke(arguments: Buffer): C = substituteFully(ring, arguments) /** * Substitutes provided [arguments] into [this] polynomial. */ - @Suppress("NOTHING_TO_INLINE") @JvmName("invokePolynomial") public inline operator fun NumberedPolynomial.invoke(arguments: Buffer>): NumberedPolynomial = substitute(ring, arguments) /** * Substitutes provided [arguments] into [this] polynomial. */ - @Suppress("NOTHING_TO_INLINE") @JvmName("invokeRationalFunction") public inline operator fun NumberedPolynomial.invoke(arguments: Buffer>): NumberedRationalFunction = substitute(ring, arguments) /** * Substitutes provided [arguments] into [this] rational function. */ - @Suppress("NOTHING_TO_INLINE") @JvmName("invokePolynomial") public inline operator fun NumberedRationalFunction.invoke(arguments: Buffer>): NumberedRationalFunction = substitute(ring, arguments) /** * Substitutes provided [arguments] into [this] rational function. */ - @Suppress("NOTHING_TO_INLINE") @JvmName("invokeRationalFunction") public inline operator fun NumberedRationalFunction.invoke(arguments: Buffer>): NumberedRationalFunction = substitute(ring, arguments) } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt index 7586b7012..f3fa32334 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt @@ -3,7 +3,7 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -@file:Suppress("FunctionName", "NOTHING_TO_INLINE") +@file:Suppress("FunctionName") package space.kscience.kmath.functions @@ -309,21 +309,18 @@ public class LabeledPolynomialTermSignatureBuilder { * * Declaring another power of the same variable will increase its degree by received degree. */ - @Suppress("NOTHING_TO_INLINE") 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. */ - @Suppress("NOTHING_TO_INLINE") 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. */ - @Suppress("NOTHING_TO_INLINE") public inline infix fun Symbol.of(deg: UInt): Unit = this inPowerOf deg } @@ -370,7 +367,6 @@ public class LabeledPolynomialBuilder( * 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. */ - @Suppress("NOTHING_TO_INLINE") public inline infix fun C.with(noinline block: LabeledPolynomialTermSignatureBuilder.() -> Unit): Unit = this.invoke(block) /** * Declares monomial with [this] coefficient and signature constructed by [block]. diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt index 3cd398623..0a0e6d902 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt @@ -3,7 +3,7 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -@file:Suppress("FunctionName", "NOTHING_TO_INLINE") +@file:Suppress("FunctionName") package space.kscience.kmath.functions @@ -296,21 +296,18 @@ public class NumberedPolynomialTermSignatureBuilder { * * Declaring another power of the same variable will increase its degree by received degree. */ - @Suppress("NOTHING_TO_INLINE") 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. */ - @Suppress("NOTHING_TO_INLINE") 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. */ - @Suppress("NOTHING_TO_INLINE") public inline infix fun Int.of(deg: UInt): Unit = this inPowerOf deg } @@ -358,7 +355,6 @@ public class NumberedPolynomialBuilder( * 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. */ - @Suppress("NOTHING_TO_INLINE") public inline infix fun C.with(noinline block: NumberedPolynomialTermSignatureBuilder.() -> Unit): Unit = this.invoke(block) /** * Declares monomial with [this] coefficient and signature constructed by [block]. -- 2.34.1 From 0ef2258665d3571b67a48933b43f0896b0ca80df Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Mon, 27 Jun 2022 17:11:39 +0300 Subject: [PATCH 106/275] Removed extra suppresses. --- .../kscience/kmath/functions/NumberedPolynomial.kt | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index eadeb68ab..8bcfbae5b 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -385,56 +385,46 @@ public class NumberedPolynomialSpace>( /** * Substitutes provided arguments [arguments] into [this] polynomial. */ - @Suppress("NOTHING_TO_INLINE") public inline fun NumberedPolynomial.substitute(arguments: Map): NumberedPolynomial = substitute(ring, arguments) /** * Substitutes provided arguments [arguments] into [this] polynomial. */ - @Suppress("NOTHING_TO_INLINE") @JvmName("substitutePolynomial") public inline fun NumberedPolynomial.substitute(arguments: Map>) : NumberedPolynomial = substitute(ring, arguments) /** * Substitutes provided arguments [arguments] into [this] polynomial. */ - @Suppress("NOTHING_TO_INLINE") public inline fun NumberedPolynomial.substitute(arguments: Buffer): NumberedPolynomial = substitute(ring, arguments) /** * Substitutes provided arguments [arguments] into [this] polynomial. */ - @Suppress("NOTHING_TO_INLINE") @JvmName("substitutePolynomial") public inline fun NumberedPolynomial.substitute(arguments: Buffer>) : NumberedPolynomial = substitute(ring, arguments) /** * Substitutes provided arguments [arguments] into [this] polynomial. */ - @Suppress("NOTHING_TO_INLINE") public inline fun NumberedPolynomial.substituteFully(arguments: Buffer): C = this.substituteFully(ring, arguments) /** * Represent [this] polynomial as a regular context-less function. */ - @Suppress("NOTHING_TO_INLINE") public inline fun NumberedPolynomial.asFunction(): (Buffer) -> C = asFunctionOver(ring) /** * Represent [this] polynomial as a regular context-less function. */ - @Suppress("NOTHING_TO_INLINE") public inline fun NumberedPolynomial.asFunctionOfConstant(): (Buffer) -> C = asFunctionOfConstantOver(ring) /** * Represent [this] polynomial as a regular context-less function. */ - @Suppress("NOTHING_TO_INLINE") public inline fun NumberedPolynomial.asFunctionOfPolynomial(): (Buffer>) -> NumberedPolynomial = asFunctionOfPolynomialOver(ring) /** * Evaluates value of [this] polynomial on provided [arguments]. */ - @Suppress("NOTHING_TO_INLINE") public inline operator fun NumberedPolynomial.invoke(arguments: Buffer): C = substituteFully(ring, arguments) /** * Substitutes provided [arguments] into [this] polynomial. */ - @Suppress("NOTHING_TO_INLINE") @JvmName("invokePolynomial") public inline operator fun NumberedPolynomial.invoke(arguments: Buffer>): NumberedPolynomial = substitute(ring, arguments) } \ No newline at end of file -- 2.34.1 From 043d292eca11f5ffea1ceb0f507a0bd101dbb399 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Mon, 27 Jun 2022 17:14:03 +0300 Subject: [PATCH 107/275] Added test. Fixed bug in NumberedPolynomial's DSL. --- .../kmath/functions/NumberedPolynomial.kt | 12 +- .../kmath/functions/numberedConstructors.kt | 1 + .../functions/NumberedConstructorsTest.kt | 20 +- .../kmath/functions/NumberedPolynomialTest.kt | 304 +++++++++++++++++- 4 files changed, 324 insertions(+), 13 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index 8bcfbae5b..35d0c7448 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -331,13 +331,13 @@ public class NumberedPolynomialSpace>( * the result is `-1`. */ public val NumberedPolynomial.lastVariable: Int - get() = coefficients.entries.maxOfOrNull { (degs, _) -> degs.lastIndex } ?: -1 + 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.entries.maxOfOrNull { (degs, _) -> degs.sum().toInt() } ?: -1 + 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. @@ -348,7 +348,7 @@ public class NumberedPolynomialSpace>( public val NumberedPolynomial.degrees: List get() = MutableList(lastVariable + 1) { 0u }.apply { - coefficients.entries.forEach { (degs, _) -> + coefficients.keys.forEach { degs -> degs.forEachIndexed { index, deg -> this[index] = max(this[index], deg) } @@ -358,13 +358,13 @@ public class NumberedPolynomialSpace>( * Counts degree of the polynomial by the specified [variable]. */ public fun NumberedPolynomial.degreeBy(variable: Int): UInt = - coefficients.entries.maxOfOrNull { (degs, _) -> degs.getOrElse(variable) { 0u } } ?: 0u + 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.entries.maxOfOrNull { (degs, _) -> - degs.withIndex().filter { (index, _) -> index in variables }.sumOf { it.value } + 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, diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt index 0a0e6d902..d561e06ba 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt @@ -283,6 +283,7 @@ public class NumberedPolynomialTermSignatureBuilder { * 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 - 1 if (index > signature.lastIndex) { signature.addAll(List(index - signature.lastIndex - 1) { 0u }) diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt index 14493aaae..8d1b128cf 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt @@ -23,8 +23,8 @@ class NumberedConstructorsTest { ), Int.algebra.numberedPolynomialSpace { NumberedPolynomial { - 5 { 1 inPowerOf 2u; 3 inPowerOf 3u } - (-6) { 2 inPowerOf 1u } + 5 { 1 pow 2u; 3 pow 3u } + (-6) { 2 pow 1u } } }, "test 1" @@ -47,8 +47,20 @@ class NumberedConstructorsTest { ), Int.algebra.numberedPolynomialSpace { NumberedPolynomial { - 5 { 1 inPowerOf 1u; 1 inPowerOf 1u } - (-6) { 1 inPowerOf 2u } + 5 { 1 pow 1u; 1 pow 1u } + (-6) { 1 pow 2u } + } + }, + "test 3" + ) + assertEquals( + NumberedPolynomialAsIs( + listOf(2u) to -1, + ), + Int.algebra.numberedPolynomialSpace { + NumberedPolynomial { + 5 { 1 pow 1u; 1 pow 1u } + (-6) { 1 pow 2u; 3 pow 0u } } }, "test 3" diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt index 537e3b85d..223ff5d92 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt @@ -9,9 +9,7 @@ package space.kscience.kmath.functions import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.test.misc.* -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertSame +import kotlin.test.* @UnstableKMathAPI @@ -1365,4 +1363,304 @@ class NumberedPolynomialTest { ) } } + @Test + fun test_lastVariable() { + val o = Rational(0) + RationalField.numberedPolynomialSpace { + assertEquals( + -1, + NumberedPolynomial {}.lastVariable, + "test 1" + ) + assertEquals( + -1, + NumberedPolynomial { + o {} + }.lastVariable, + "test 2" + ) + assertEquals( + 2, + NumberedPolynomial { + o { 1 pow 1u; 2 pow 2u; 3 pow 3u } + }.lastVariable, + "test 3" + ) + assertEquals( + 3, + NumberedPolynomial { + o { 1 pow 0u; 2 pow 1u; 3 pow 2u; 4 pow 1u; 5 pow 0u } + }.also { println(it) }.lastVariable, + "test 4" + ) + assertEquals( + 2, + NumberedPolynomial { + o {} + o { 2 pow 1u } + o { 1 pow 2u; 3 pow 1u } + }.lastVariable, + "test 5" + ) + } + } + @Test + fun test_degree() { + val o = Rational(0) + RationalField.numberedPolynomialSpace { + assertEquals( + -1, + NumberedPolynomial {}.degree, + "test 1" + ) + assertEquals( + 0, + NumberedPolynomial { + o {} + }.degree, + "test 2" + ) + assertEquals( + 6, + NumberedPolynomial { + o { 1 pow 1u; 2 pow 2u; 3 pow 3u } + }.degree, + "test 3" + ) + assertEquals( + 4, + NumberedPolynomial { + o { 1 pow 0u; 2 pow 1u; 3 pow 2u; 4 pow 1u; 5 pow 0u } + }.degree, + "test 4" + ) + assertEquals( + 3, + NumberedPolynomial { + o {} + o { 2 pow 1u } + o { 1 pow 2u; 3 pow 1u } + }.degree, + "test 5" + ) + assertEquals( + 4, + NumberedPolynomial { + o {} + o { 2 pow 1u } + o { 1 pow 2u; 3 pow 1u } + o { 4 pow 4u } + }.degree, + "test 6" + ) + } + } + @Test + fun test_countOfVariables() { + val o = Rational(0) + RationalField.numberedPolynomialSpace { + assertEquals( + listOf(), + NumberedPolynomial {}.degrees, + "test 1" + ) + assertEquals( + listOf(), + NumberedPolynomial { + o {} + }.degrees, + "test 2" + ) + assertEquals( + listOf(1u, 2u, 3u), + NumberedPolynomial { + o { 1 pow 1u; 2 pow 2u; 3 pow 3u } + }.degrees, + "test 3" + ) + assertEquals( + listOf(0u, 1u, 2u, 1u), + NumberedPolynomial { + o { 1 pow 0u; 2 pow 1u; 3 pow 2u; 4 pow 1u; 5 pow 0u } + }.degrees, + "test 4" + ) + assertEquals( + listOf(2u, 1u, 1u), + NumberedPolynomial { + o {} + o { 2 pow 1u } + o { 1 pow 2u; 3 pow 1u } + }.degrees, + "test 5" + ) + assertEquals( + listOf(2u, 2u, 2u, 4u), + NumberedPolynomial { + o {} + o { 1 pow 1u; 2 pow 2u } + o { 2 pow 1u; 3 pow 2u } + o { 1 pow 2u; 3 pow 1u } + o { 4 pow 4u } + }.degrees, + "test 6" + ) + } + } + @Test + fun test_degreeBy() { + val o = Rational(0) + 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 { + o {} + }.collectDegrees(), + "test 2" + ) + assertEquals( + listOf(1u, 2u, 3u, 0u), + NumberedPolynomial { + o { 1 pow 1u; 2 pow 2u; 3 pow 3u } + }.collectDegrees(), + "test 3" + ) + assertEquals( + listOf(0u, 1u, 2u, 1u, 0u), + NumberedPolynomial { + o { 1 pow 0u; 2 pow 1u; 3 pow 2u; 4 pow 1u; 5 pow 0u } + }.collectDegrees(), + "test 4" + ) + assertEquals( + listOf(2u, 1u, 1u, 0u), + NumberedPolynomial { + o {} + o { 2 pow 1u } + o { 1 pow 2u; 3 pow 1u } + }.collectDegrees(), + "test 5" + ) + assertEquals( + listOf(2u, 2u, 2u, 4u, 0u), + NumberedPolynomial { + o {} + o { 1 pow 1u; 2 pow 2u } + o { 2 pow 1u; 3 pow 2u } + o { 1 pow 2u; 3 pow 1u } + o { 4 pow 4u } + }.collectDegrees(), + "test 6" + ) + } + } + @Test + fun test_degreeBy_Collection() { + val o = Rational(0) + 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 { + o {} + }.checkDegreeBy("test 2") + NumberedPolynomial { + o { 1 pow 1u; 2 pow 2u; 3 pow 3u } + }.checkDegreeBy("test 3") + NumberedPolynomial { + o { 1 pow 0u; 2 pow 1u; 3 pow 2u; 4 pow 1u; 5 pow 0u } + }.checkDegreeBy("test 4") + NumberedPolynomial { + o {} + o { 2 pow 1u } + o { 1 pow 2u; 3 pow 1u } + }.checkDegreeBy("test 5") + NumberedPolynomial { + o {} + o { 1 pow 1u; 2 pow 2u } + o { 2 pow 1u; 3 pow 2u } + o { 1 pow 2u; 3 pow 1u } + o { 4 pow 4u } + }.checkDegreeBy("test 6") + } + } + @Test + fun test_degrees() { + val o = Rational(0) + RationalField.numberedPolynomialSpace { + assertEquals( + 0, + NumberedPolynomial {}.countOfVariables, + "test 1" + ) + assertEquals( + 0, + NumberedPolynomial { + o {} + }.countOfVariables, + "test 2" + ) + assertEquals( + 3, + NumberedPolynomial { + o { 1 pow 1u; 2 pow 2u; 3 pow 3u } + }.countOfVariables, + "test 3" + ) + assertEquals( + 3, + NumberedPolynomial { + o { 1 pow 0u; 2 pow 1u; 3 pow 2u; 4 pow 1u; 5 pow 0u } + }.countOfVariables, + "test 4" + ) + assertEquals( + 3, + NumberedPolynomial { + o {} + o { 2 pow 1u } + o { 1 pow 2u; 3 pow 1u } + }.countOfVariables, + "test 5" + ) + assertEquals( + 4, + NumberedPolynomial { + o {} + o { 1 pow 1u; 2 pow 2u } + o { 2 pow 1u; 3 pow 2u } + o { 1 pow 2u; 3 pow 1u } + o { 4 pow 4u } + }.countOfVariables, + "test 6" + ) + } + } } \ No newline at end of file -- 2.34.1 From da46ea923c52c586cb9351d922281df6f1f36bf4 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 28 Jun 2022 15:07:09 +0300 Subject: [PATCH 108/275] Extended test for NumberedPolynomial --- .../kmath/functions/NumberedPolynomialTest.kt | 80 ++++++++++++++++++- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt index 223ff5d92..dac7c1a62 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt @@ -1456,7 +1456,7 @@ class NumberedPolynomialTest { } } @Test - fun test_countOfVariables() { + fun test_degrees() { val o = Rational(0) RationalField.numberedPolynomialSpace { assertEquals( @@ -1612,7 +1612,7 @@ class NumberedPolynomialTest { } } @Test - fun test_degrees() { + fun test_countOfVariables() { val o = Rational(0) RationalField.numberedPolynomialSpace { assertEquals( @@ -1663,4 +1663,80 @@ class NumberedPolynomialTest { ) } } + @Test + fun test_RF_countOfVariables() { + val o = Rational(0) + RationalField.numberedRationalFunctionSpace { + assertEquals( + 0, + NumberedRationalFunction( + NumberedPolynomial {} + ).countOfVariables, + "test 1" + ) + assertEquals( + 0, + NumberedRationalFunction( + NumberedPolynomial {}, + NumberedPolynomial {} + ).countOfVariables, + "test 2" + ) + assertEquals( + 0, + NumberedRationalFunction( + NumberedPolynomial { + o {} + } + ).countOfVariables, + "test 3" + ) + assertEquals( + 3, + NumberedRationalFunction( + NumberedPolynomial { + o { 1 pow 1u; 2 pow 2u; 3 pow 3u } + } + ).countOfVariables, + "test 4" + ) + assertEquals( + 3, + NumberedRationalFunction( + NumberedPolynomial { + o { 2 pow 1u; 4 pow 1u } + }, + NumberedPolynomial { + o { 1 pow 0u; 3 pow 2u; 5 pow 0u } + } + ).countOfVariables, + "test 5" + ) + assertEquals( + 3, + NumberedRationalFunction( + NumberedPolynomial { + o {} + o { 2 pow 1u } + o { 1 pow 2u; 3 pow 1u } + } + ).countOfVariables, + "test 6" + ) + assertEquals( + 4, + NumberedRationalFunction( + NumberedPolynomial { + o {} + o { 1 pow 1u; 2 pow 2u } + o { 1 pow 2u; 3 pow 1u } + }, NumberedPolynomial { + o { 2 pow 1u; 3 pow 2u } + o { 4 pow 4u } + } + ).countOfVariables, + "test 7" + ) + } + } } \ No newline at end of file -- 2.34.1 From 64b33aed184e0f52a4f2938022cf6e0eae0e8591 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Wed, 29 Jun 2022 14:53:12 +0300 Subject: [PATCH 109/275] Remove extra suppresses. --- .../kotlin/space/kscience/kmath/test/misc/IntModulo.kt | 2 +- .../kotlin/space/kscience/kmath/test/misc/Rational.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt index afd2b5add..b3bb4faf7 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt @@ -108,7 +108,7 @@ class IntModulo { override fun toString(): String = "$residue mod $modulus" } -@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") +@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE") class IntModuloRing : Ring { val modulus: Int diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt index 72bb5942c..4bdd60704 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt @@ -114,7 +114,7 @@ class Rational { override fun toString(): String = if (denominator == 1L) "$numerator" else "$numerator/$denominator" } -@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") +@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE") @OptIn(UnstableKMathAPI::class) object RationalField : Field, NumbersAddOps { override inline val zero: Rational get() = Rational.ZERO -- 2.34.1 From c8b9951f46c27f7af85f43188af9eb9d6e3cb48d Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Wed, 29 Jun 2022 14:54:49 +0300 Subject: [PATCH 110/275] Added for list utilities for rational functions. --- .../kmath/functions/ListPolynomialUtilTest.kt | 725 +++++++++++++++++- 1 file changed, 718 insertions(+), 7 deletions(-) diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt index 69c1611f3..314044ba8 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt @@ -8,6 +8,7 @@ package space.kscience.kmath.functions import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.test.misc.Rational import space.kscience.kmath.test.misc.RationalField +import kotlin.test.Ignore import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFailsWith @@ -16,7 +17,7 @@ import kotlin.test.assertFailsWith @OptIn(UnstableKMathAPI::class) class ListPolynomialUtilTest { @Test - fun test_substitute_Double() { + fun test_Polynomial_substitute_Double() { assertEquals( 0.0, ListPolynomial(1.0, -2.0, 1.0).substitute(1.0), @@ -49,7 +50,7 @@ class ListPolynomialUtilTest { ) } @Test - fun test_substitute_Constant() { + fun test_Polynomial_substitute_Constant() { assertEquals( Rational(0), ListPolynomial(Rational(1), Rational(-2), Rational(1)).substitute(RationalField, Rational(1)), @@ -81,7 +82,7 @@ class ListPolynomialUtilTest { ) } @Test - fun test_substitute_Polynomial() { + fun test_Polynomial_substitute_Polynomial() { assertEquals( ListPolynomial(Rational(0)), ListPolynomial(Rational(1), Rational(-2), Rational(1)).substitute(RationalField, ListPolynomial(Rational(1))), @@ -119,7 +120,717 @@ class ListPolynomialUtilTest { ) } @Test - fun test_derivative() { + @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 make 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 make 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), @@ -142,7 +853,7 @@ class ListPolynomialUtilTest { ) } @Test - fun test_nthDerivative() { + fun test_Polynomial_nthDerivative() { assertEquals( ListPolynomial(Rational(-2), Rational(2)), ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, 1), @@ -188,7 +899,7 @@ class ListPolynomialUtilTest { ) } @Test - fun test_antiderivative() { + fun test_Polynomial_antiderivative() { assertEquals( ListPolynomial(Rational(0), Rational(1), Rational(-1), Rational(1, 3)), ListPolynomial(Rational(1), Rational(-2), Rational(1)).antiderivative(RationalField), @@ -211,7 +922,7 @@ class ListPolynomialUtilTest { ) } @Test - fun test_nthAntiderivative() { + 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), -- 2.34.1 From f147636e9d0402dd4c4d3b4c0e73e8a0c12a4d57 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Fri, 1 Jul 2022 14:46:05 +0300 Subject: [PATCH 111/275] Tests generation for numbered utilities in progress. --- .../space/kscience/kmath/functions/misc.kt | 4 +- .../functions/NumberedPolynomialUtilTest.kt | 2113 ++++++++++++++++- 2 files changed, 2074 insertions(+), 43 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt index aba246519..76f1c294e 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt @@ -17,6 +17,6 @@ package space.kscience.kmath.functions "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.WARNING + level = RequiresOptIn.Level.ERROR ) -internal annotation class DelicatePolynomialAPI \ No newline at end of file +public annotation class DelicatePolynomialAPI \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt index ecad6198e..8ece66145 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt @@ -8,13 +8,14 @@ package space.kscience.kmath.functions import space.kscience.kmath.test.misc.Rational import space.kscience.kmath.test.misc.RationalField import space.kscience.kmath.test.misc.assertContentEquals +import kotlin.test.Ignore import kotlin.test.Test import kotlin.test.assertEquals class NumberedPolynomialUtilTest { @Test - fun test_substitute_Double_Map() { + fun test_Polynomial_substitute_Double_Map() { assertContentEquals( mapOf(emptyList() to 0.0), NumberedPolynomialAsIs( @@ -53,6 +54,34 @@ class NumberedPolynomialUtilTest { 0.001, "test 2" ) + assertContentEquals( + mapOf( + 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 + )).coefficients, + 0.001, + "test 2'" + ) assertContentEquals( mapOf( listOf() to 0.8597048543814783, @@ -75,6 +104,29 @@ class NumberedPolynomialUtilTest { 0.001, "test 3" ) + assertContentEquals( + mapOf( + 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 + )).coefficients, + 0.001, + "test 3'" + ) assertContentEquals( mapOf( listOf() to 1.433510890645169, @@ -97,6 +149,29 @@ class NumberedPolynomialUtilTest { 0.001, "test 4" ) + assertContentEquals( + mapOf( + 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 + )).coefficients, + 0.001, + "test 4'" + ) assertContentEquals( mapOf( listOf() to 1.934530767358133, @@ -120,15 +195,7 @@ class NumberedPolynomialUtilTest { ) assertContentEquals( mapOf( - 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, + listOf() to 1.934530767358133, ), NumberedPolynomialAsIs( listOf() to 0.8597048543814783, @@ -141,14 +208,16 @@ class NumberedPolynomialUtilTest { 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 )).coefficients, 0.001, - "test 6" + "test 5'" ) } @Test - fun test_substitute_Constant() { + fun test_Polynomial_substitute_Constant_Map() { assertEquals( NumberedPolynomialAsIs( listOf() to Rational(0) @@ -183,6 +252,167 @@ class NumberedPolynomialUtilTest { )), "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( @@ -202,37 +432,11 @@ class NumberedPolynomialUtilTest { 0 to Rational(-2, 5), 1 to Rational(12, 9), )), - "test 3" - ) - // 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(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), - ), - 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()), - "test 4" + "test 6" ) } @Test - fun test_substitute_Polynomial() { + fun test_Polynomial_substitute_Polynomial_Map() { assertEquals( NumberedPolynomialAsIs( listOf() to Rational(0) @@ -248,7 +452,7 @@ class NumberedPolynomialUtilTest { )), "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 + // 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), @@ -289,5 +493,1832 @@ class NumberedPolynomialUtilTest { )), "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 make 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 + @Ignore + fun test_RationalFunction_substitute_Double_Map() { + // TODO + } + @Test + @Ignore + fun test_RationalFunction_substitute_Constant_Map() { + // TODO + } + @Test + @Ignore + fun test_RationalFunction_substitute_Polynomial_Map() { + // TODO + } + @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 make denominator r^deg(p), + // not r^(deg(p)(deg(p)+1)/2) as it is now. + fun test_RationalFunction_substitute_RationalFunction_Map() { + // TODO + } + @Test + @Ignore + fun test_Polynomial_substitute_Double_Buffer() { + // TODO + } + @Test + @Ignore + fun test_Polynomial_substitute_Constant_Buffer() { + // TODO + } + @Test + @Ignore + fun test_Polynomial_substitute_Polynomial_Buffer() { + // TODO + } + @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 make denominator r^deg(p), + // not r^(deg(p)(deg(p)+1)/2) as it is now. + fun test_Polynomial_substitute_RationalFunction_Buffer() { + // TODO + } + @Test + @Ignore + fun test_RationalFunction_substitute_Double_Buffer() { + // TODO + } + @Test + @Ignore + fun test_RationalFunction_substitute_Constant_Buffer() { + // TODO + } + @Test + @Ignore + fun test_RationalFunction_substitute_Polynomial_Buffer() { + // TODO + } + @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 make denominator r^deg(p), + // not r^(deg(p)(deg(p)+1)/2) as it is now. + fun test_RationalFunction_substitute_RationalFunction_Buffer() { + // TODO + } + @Test + @Ignore + fun test_Polynomial_substituteFully_Double_Buffer() { + // TODO + } + @Test + @Ignore + fun test_Polynomial_substituteFully_Constant_Buffer() { + // TODO + } + @Test + @Ignore + fun test_RationalFunction_substituteFully_Double_Buffer() { + // TODO + } + @Test + @Ignore + fun test_RationalFunction_substituteFully_Constant_Buffer() { + // TODO + } + @Test + @Ignore + fun test_Polynomial_derivativeWithRespectTo_variable() { + // TODO + } + @Test + @Ignore + fun test_Polynomial_nthDerivativeWithRespectTo_variable_order() { + // TODO + } + @Test + @Ignore + fun test_Polynomial_nthDerivativeWithRespectTo_variablesAndOrders() { + // TODO + } + @Test + @Ignore + fun test_Polynomial_antiderivativeWithRespectTo_variable() { + // TODO + } + @Test + @Ignore + fun test_Polynomial_nthAntiderivativeWithRespectTo_variable_order() { + // TODO + } + @Test + @Ignore + fun test_Polynomial_nthAntiderivativeWithRespectTo_variablesAndOrders() { + // TODO } } \ No newline at end of file -- 2.34.1 From 672a3c1552332eb8530fbc71a50c72894ddd5073 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sun, 3 Jul 2022 15:47:12 +0300 Subject: [PATCH 112/275] Tests generation for numbered utilities in progress: finish map-wise substitutions. Also: - Upgrade operations on Rational. - Add new assertions. - Changed a bit FIXME comments. --- .../kmath/functions/ListPolynomialUtilTest.kt | 4 +- .../functions/NumberedPolynomialUtilTest.kt | 3248 ++++++++++++++++- .../kscience/kmath/test/misc/Rational.kt | 111 +- .../kscience/kmath/test/misc/assertion.kt | 34 + 4 files changed, 3321 insertions(+), 76 deletions(-) diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt index 314044ba8..9d4f4411b 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt @@ -121,7 +121,7 @@ class ListPolynomialUtilTest { } @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 make denominator r^deg(p), + // 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( @@ -589,7 +589,7 @@ class ListPolynomialUtilTest { } @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 make denominator r^deg(p), + // 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( diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt index 8ece66145..b6baed6af 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt @@ -7,7 +7,7 @@ package space.kscience.kmath.functions import space.kscience.kmath.test.misc.Rational import space.kscience.kmath.test.misc.RationalField -import space.kscience.kmath.test.misc.assertContentEquals +import space.kscience.kmath.test.misc.assertEquals import kotlin.test.Ignore import kotlin.test.Test import kotlin.test.assertEquals @@ -16,20 +16,20 @@ import kotlin.test.assertEquals class NumberedPolynomialUtilTest { @Test fun test_Polynomial_substitute_Double_Map() { - assertContentEquals( - mapOf(emptyList() to 0.0), + 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 - )).coefficients, + )), 0.001, "test 1" ) - assertContentEquals( - mapOf( + assertEquals( + NumberedPolynomialAsIs( listOf() to 0.8597048543814783, listOf(1u) to 0.22997637465889875, listOf(2u) to 0.32675302591924016, @@ -50,12 +50,12 @@ class NumberedPolynomialUtilTest { listOf(0u, 2u) to 0.2700930201481795, listOf(1u, 2u) to -0.06962351375204712, listOf(2u, 2u) to -0.015206988092131501, - ).substitute(mapOf()).coefficients, + ).substitute(mapOf()), 0.001, "test 2" ) - assertContentEquals( - mapOf( + assertEquals( + NumberedPolynomialAsIs( listOf() to 0.8597048543814783, listOf(1u) to 0.22997637465889875, listOf(2u) to 0.32675302591924016, @@ -78,12 +78,12 @@ class NumberedPolynomialUtilTest { listOf(2u, 2u) to -0.015206988092131501, ).substitute(mapOf( 5 to 0.9211194782050933 - )).coefficients, + )), 0.001, "test 2'" ) - assertContentEquals( - mapOf( + assertEquals( + NumberedPolynomialAsIs( listOf() to 0.8597048543814783, listOf(0u, 1u) to 0.4561746111587508, listOf(0u, 2u) to 0.2700930201481795, @@ -100,12 +100,12 @@ class NumberedPolynomialUtilTest { listOf(2u, 2u) to -0.015206988092131501, ).substitute(mapOf( 0 to 0.0 - )).coefficients, + )), 0.001, "test 3" ) - assertContentEquals( - mapOf( + assertEquals( + NumberedPolynomialAsIs( listOf() to 0.8597048543814783, listOf(0u, 1u) to 0.4561746111587508, listOf(0u, 2u) to 0.2700930201481795, @@ -123,12 +123,12 @@ class NumberedPolynomialUtilTest { ).substitute(mapOf( 0 to 0.0, 5 to 0.9211194782050933 - )).coefficients, + )), 0.001, "test 3'" ) - assertContentEquals( - mapOf( + assertEquals( + NumberedPolynomialAsIs( listOf() to 1.433510890645169, listOf(1u) to 0.6264844682514724, listOf(2u) to 0.8405727903771333, @@ -145,12 +145,12 @@ class NumberedPolynomialUtilTest { listOf(2u, 2u) to -0.015206988092131501, ).substitute(mapOf( 1 to 0.8400458576651112 - )).coefficients, + )), 0.001, "test 4" ) - assertContentEquals( - mapOf( + assertEquals( + NumberedPolynomialAsIs( listOf() to 1.433510890645169, listOf(1u) to 0.6264844682514724, listOf(2u) to 0.8405727903771333, @@ -168,12 +168,12 @@ class NumberedPolynomialUtilTest { ).substitute(mapOf( 1 to 0.8400458576651112, 5 to 0.9211194782050933 - )).coefficients, + )), 0.001, "test 4'" ) - assertContentEquals( - mapOf( + assertEquals( + NumberedPolynomialAsIs( listOf() to 1.934530767358133, ), NumberedPolynomialAsIs( @@ -189,12 +189,12 @@ class NumberedPolynomialUtilTest { ).substitute(mapOf( 0 to 0.4846192734143442, 1 to 0.8400458576651112, - )).coefficients, + )), 0.001, "test 5" ) - assertContentEquals( - mapOf( + assertEquals( + NumberedPolynomialAsIs( listOf() to 1.934530767358133, ), NumberedPolynomialAsIs( @@ -211,7 +211,7 @@ class NumberedPolynomialUtilTest { 0 to 0.4846192734143442, 1 to 0.8400458576651112, 5 to 0.9211194782050933 - )).coefficients, + )), 0.001, "test 5'" ) @@ -1086,7 +1086,7 @@ class NumberedPolynomialUtilTest { } @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 make denominator r^deg(p), + // 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( @@ -2206,26 +2206,3198 @@ class NumberedPolynomialUtilTest { ) } @Test - @Ignore fun test_RationalFunction_substitute_Double_Map() { - // TODO + 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 - @Ignore fun test_RationalFunction_substitute_Constant_Map() { - // TODO + 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 - @Ignore fun test_RationalFunction_substitute_Polynomial_Map() { - // TODO + 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 make denominator r^deg(p), + // 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() { // TODO + 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 @Ignore @@ -2244,7 +5416,7 @@ class NumberedPolynomialUtilTest { } @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 make denominator r^deg(p), + // 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() { // TODO @@ -2266,7 +5438,7 @@ class NumberedPolynomialUtilTest { } @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 make denominator r^deg(p), + // 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() { // TODO diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt index 4bdd60704..071701593 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt @@ -41,66 +41,105 @@ class Rational { operator fun unaryPlus(): Rational = this operator fun unaryMinus(): Rational = Rational(-this.numerator, this.denominator) - operator fun plus(other: Rational): Rational = - Rational( - numerator * other.denominator + denominator * other.numerator, - denominator * other.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 + denominator, + toCheckInput = false ) operator fun plus(other: Long): Rational = Rational( numerator + denominator * other, - denominator + denominator, + toCheckInput = false ) - operator fun minus(other: Rational): Rational = - Rational( - numerator * other.denominator - denominator * other.numerator, - denominator * other.denominator + 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 + denominator, + toCheckInput = false ) operator fun minus(other: Long): Rational = Rational( numerator - denominator * other, - denominator + denominator, + toCheckInput = false ) - operator fun times(other: Rational): Rational = - Rational( - numerator * other.numerator, - denominator * other.denominator + 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 = - Rational( - numerator * other.toLong(), - denominator + } + 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 = - Rational( - numerator * other, - denominator + } + 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 = - Rational( - numerator * other.denominator, - denominator * other.numerator + } + 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 = - Rational( - numerator, - denominator * other.toLong() + } + 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 = - Rational( - numerator, - denominator * other + } + 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 diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/assertion.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/assertion.kt index 52ecf416a..bf8675675 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/assertion.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/assertion.kt @@ -5,10 +5,44 @@ package space.kscience.kmath.test.misc +import space.kscience.kmath.functions.NumberedPolynomial +import space.kscience.kmath.functions.NumberedRationalFunction import kotlin.test.assertEquals 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: NumberedRationalFunction, + actual: NumberedRationalFunction, + absoluteTolerance: Double, + message: String? = null +) { + assertEquals( + expected.numerator, + actual.numerator, + absoluteTolerance, + message + ) + assertEquals( + expected.denominator, + actual.denominator, + absoluteTolerance, + message + ) } \ No newline at end of file -- 2.34.1 From 102e83b4780209da177053d587aed35aabf7f811 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Mon, 4 Jul 2022 02:24:46 +0300 Subject: [PATCH 113/275] Tests generation for numbered utilities in progress: finish substitutions. --- .../kscience/kmath/functions/numberedUtil.kt | 6 +- .../functions/NumberedPolynomialUtilTest.kt | 3786 ++++++++++++++++- .../kscience/kmath/test/misc/assertion.kt | 14 +- 3 files changed, 3780 insertions(+), 26 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt index e485652f4..9397c1956 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt @@ -262,12 +262,14 @@ public fun NumberedRationalFunction.substitute(ring: Ring, args: Buffe 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 }) { "Fully substituting buffer should cover all variables of the polynomial." } + 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()) @@ -280,7 +282,7 @@ public fun NumberedPolynomial.substituteFully(args: Buffer): Dou */ public fun NumberedPolynomial.substituteFully(ring: Ring, args: Buffer): C = ring { val lastSubstitutionVariable = args.size - 1 - require(coefficients.keys.all { it.lastIndex <= lastSubstitutionVariable }) { "Fully substituting buffer should cover all variables of the polynomial." } + 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) diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt index b6baed6af..9e49f1315 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt @@ -5,14 +5,19 @@ package space.kscience.kmath.functions +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.asBuffer import space.kscience.kmath.test.misc.Rational import space.kscience.kmath.test.misc.RationalField import space.kscience.kmath.test.misc.assertEquals +import space.kscience.kmath.test.misc.assertFailsWithTypeAndMessage import kotlin.test.Ignore import kotlin.test.Test import kotlin.test.assertEquals +fun bufferOf(vararg elements: T): Buffer = elements.asBuffer() + class NumberedPolynomialUtilTest { @Test fun test_Polynomial_substitute_Double_Map() { @@ -4104,7 +4109,6 @@ class NumberedPolynomialUtilTest { // 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() { - // TODO assertEquals( NumberedRationalFunction( NumberedPolynomialAsIs( @@ -5400,68 +5404,3804 @@ class NumberedPolynomialUtilTest { ) } @Test - @Ignore fun test_Polynomial_substitute_Double_Buffer() { - // TODO + 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 - @Ignore fun test_Polynomial_substitute_Constant_Buffer() { - // TODO + 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 - @Ignore fun test_Polynomial_substitute_Polynomial_Buffer() { - // TODO + 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() { - // TODO + 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 - @Ignore fun test_RationalFunction_substitute_Double_Buffer() { - // TODO + 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 - @Ignore fun test_RationalFunction_substitute_Constant_Buffer() { - // TODO + 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 - @Ignore fun test_RationalFunction_substitute_Polynomial_Buffer() { - // TODO + 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() { - // TODO + 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 - @Ignore fun test_Polynomial_substituteFully_Double_Buffer() { - // TODO + 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 - @Ignore fun test_Polynomial_substituteFully_Constant_Buffer() { - // TODO + 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 - @Ignore fun test_RationalFunction_substituteFully_Double_Buffer() { - // TODO + 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 - @Ignore fun test_RationalFunction_substituteFully_Constant_Buffer() { - // TODO + 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 @Ignore diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/assertion.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/assertion.kt index bf8675675..3ad482454 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/assertion.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/assertion.kt @@ -8,6 +8,7 @@ package space.kscience.kmath.test.misc 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) { @@ -45,4 +46,15 @@ fun assertEquals( absoluteTolerance, message ) -} \ No newline at end of file +} + +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 -- 2.34.1 From 39088ec36b3ab7635889fc5ca593f6684021bf54 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Mon, 4 Jul 2022 02:36:46 +0300 Subject: [PATCH 114/275] Replaced assertFailsWith with assertFailsWithTypeAndMessage. --- .../kmath/functions/ListPolynomialUtilTest.kt | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt index 9d4f4411b..685a2a506 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt @@ -8,16 +8,22 @@ package space.kscience.kmath.functions import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.test.misc.Rational import space.kscience.kmath.test.misc.RationalField +import space.kscience.kmath.test.misc.assertFailsWithTypeAndMessage import kotlin.test.Ignore import kotlin.test.Test import kotlin.test.assertEquals -import kotlin.test.assertFailsWith @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), @@ -859,7 +865,10 @@ class ListPolynomialUtilTest { ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, 1), "test 1" ) - assertFailsWith("test2") { + assertFailsWithTypeAndMessage( + "Order of derivative must be non-negative", + "test2" + ) { ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, -1) } assertEquals( @@ -928,7 +937,10 @@ class ListPolynomialUtilTest { ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, 1), "test 1" ) - assertFailsWith("test2") { + assertFailsWithTypeAndMessage( + "Order of antiderivative must be non-negative", + "test2" + ) { ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, -1) } assertEquals( -- 2.34.1 From e89e4e19d35e61240e8cb7fb00d88c4e35087991 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Mon, 4 Jul 2022 03:54:28 +0300 Subject: [PATCH 115/275] Return suppresses. --- .../kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt | 2 ++ .../space/kscience/kmath/functions/LabeledRationalFunction.kt | 2 ++ .../kotlin/space/kscience/kmath/functions/ListPolynomial.kt | 2 ++ .../space/kscience/kmath/functions/ListRationalFunction.kt | 2 ++ .../kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt | 2 ++ .../space/kscience/kmath/functions/NumberedRationalFunction.kt | 2 ++ .../space/kscience/kmath/functions/labeledConstructors.kt | 2 +- .../space/kscience/kmath/functions/numberedConstructors.kt | 2 +- .../kotlin/space/kscience/kmath/test/misc/Rational.kt | 1 + 9 files changed, 15 insertions(+), 2 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt index f1859ac4b..6d9af631a 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.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("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress") + package space.kscience.kmath.functions import space.kscience.kmath.expressions.Symbol diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt index c34d1e46f..e4f2b6c37 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.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("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress") + package space.kscience.kmath.functions import space.kscience.kmath.expressions.Symbol diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt index 3f470d5e7..a83b3915a 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.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("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress") + package space.kscience.kmath.functions import space.kscience.kmath.operations.Ring diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt index 40c6745d9..b744afc51 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.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("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress") + package space.kscience.kmath.functions import space.kscience.kmath.operations.Ring diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index 35d0c7448..ad421d7d3 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.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("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress") + package space.kscience.kmath.functions import space.kscience.kmath.operations.Ring diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt index 97dffebe1..0f3c1ced9 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.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("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress") + package space.kscience.kmath.functions import space.kscience.kmath.operations.Ring diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt index f3fa32334..7a8d961c0 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt @@ -3,7 +3,7 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -@file:Suppress("FunctionName") +@file:Suppress("FunctionName", "NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress") package space.kscience.kmath.functions diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt index d561e06ba..7f02ff1e3 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt @@ -3,7 +3,7 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -@file:Suppress("FunctionName") +@file:Suppress("FunctionName", "NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress") package space.kscience.kmath.functions diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt index 071701593..62b7dc3be 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt @@ -9,6 +9,7 @@ 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) -- 2.34.1 From e40977647ddf5637855fe9a3171d03895103ef02 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Mon, 4 Jul 2022 04:02:08 +0300 Subject: [PATCH 116/275] Added suppresses. --- .../kotlin/space/kscience/kmath/test/misc/IntModulo.kt | 2 ++ .../kotlin/space/kscience/kmath/test/misc/Rational.kt | 2 ++ 2 files changed, 4 insertions(+) diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt index b3bb4faf7..f6e8457bb 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.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("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress") + package space.kscience.kmath.test.misc import space.kscience.kmath.functions.ListPolynomial diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt index 62b7dc3be..731621658 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.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("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress") + package space.kscience.kmath.test.misc import space.kscience.kmath.misc.UnstableKMathAPI -- 2.34.1 From 45ed45bd137bb5e5f7547333ca72bf6b3d90b46d Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 5 Jul 2022 03:41:52 +0300 Subject: [PATCH 117/275] Finish tests generation for numbered utilities. Also: - Optimize a bit labeled and numbered differentiation. - Fixed bugs in numbered anti-differentiation. --- .../kscience/kmath/functions/labeledUtil.kt | 12 +- .../kscience/kmath/functions/numberedUtil.kt | 24 +- .../functions/NumberedPolynomialUtilTest.kt | 2816 ++++++++++++++++- 3 files changed, 2823 insertions(+), 29 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt index 4002eb25a..4e799cb43 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt @@ -148,7 +148,7 @@ public fun > LabeledPolynomial.derivativeWithRespectTo( variable: Symbol, ): LabeledPolynomial = algebra { LabeledPolynomial( - buildMap(coefficients.size) { + buildMap(coefficients.count { it.key.getOrElse(variable) { 0u } >= 1u }) { coefficients .forEach { (degs, c) -> if (variable !in degs) return@forEach @@ -179,7 +179,7 @@ public fun > LabeledPolynomial.nthDerivativeWithRespectTo( ): LabeledPolynomial = algebra { if (order == 0u) return this@nthDerivativeWithRespectTo LabeledPolynomial( - buildMap(coefficients.size) { + buildMap(coefficients.count { it.key.getOrElse(variable) { 0u } >= order }) { coefficients .forEach { (degs, c) -> if (degs.getOrElse(variable) { 0u } < order) return@forEach @@ -213,7 +213,13 @@ public fun > LabeledPolynomial.nthDerivativeWithRespectTo( val filteredVariablesAndOrders = variablesAndOrders.filterValues { it != 0u } if (filteredVariablesAndOrders.isEmpty()) return this@nthDerivativeWithRespectTo LabeledPolynomial( - buildMap(coefficients.size) { + 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 diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt index 9397c1956..9d88cd648 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt @@ -352,7 +352,7 @@ public fun > NumberedPolynomial.derivativeWithRespectTo( variable: Int, ): NumberedPolynomial = ring { NumberedPolynomial( - buildMap(coefficients.size) { + buildMap(coefficients.count { it.key.getOrElse(variable) { 0u } >= 1u }) { coefficients .forEach { (degs, c) -> if (degs.lastIndex < variable) return@forEach @@ -382,7 +382,7 @@ public fun > NumberedPolynomial.nthDerivativeWithRespectTo( ): NumberedPolynomial = ring { if (order == 0u) return this@nthDerivativeWithRespectTo NumberedPolynomial( - buildMap(coefficients.size) { + buildMap(coefficients.count { it.key.getOrElse(variable) { 0u } >= order }) { coefficients .forEach { (degs, c) -> if (degs.lastIndex < variable) return@forEach @@ -451,8 +451,8 @@ public fun > NumberedPolynomial.antiderivativeWithRespectTo( coefficients .forEach { (degs, c) -> put( - List(max(variable + 1, degs.size)) { if (it != variable) degs[it] else degs[it] + 1u }, - c / multiplyByDoubling(one, degs[variable]) + List(max(variable + 1, degs.size)) { degs.getOrElse(it) { 0u } + if (it != variable) 0u else 1u }, + c / multiplyByDoubling(one, degs.getOrElse(variable) { 0u } + 1u) ) } } @@ -474,9 +474,9 @@ public fun > NumberedPolynomial.nthAntiderivativeWithRespectT coefficients .forEach { (degs, c) -> put( - List(max(variable + 1, degs.size)) { if (it != variable) degs[it] else degs[it] + order }, - degs[variable].let { deg -> - (deg downTo deg - order + 1u) + 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) } } ) @@ -501,11 +501,11 @@ public fun > NumberedPolynomial.nthAntiderivativeWithRespectT coefficients .forEach { (degs, c) -> put( - List(max(maxRespectedVariable + 1, degs.size)) { degs[it] + filteredVariablesAndOrders.getOrElse(it) { 0u } }, - filteredVariablesAndOrders.entries.fold(c) { acc1, (index, order) -> - degs[index].let { deg -> - (deg downTo deg - order + 1u) - .fold(acc1) { acc2, ord -> acc2 / multiplyByDoubling(one, ord) } + 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) } } } ) diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt index 9e49f1315..1b87d3fcf 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.functions +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asBuffer import space.kscience.kmath.test.misc.Rational @@ -8832,7 +8833,7 @@ class NumberedPolynomialUtilTest { listOf(0u, 2u) to Rational(5, 5), listOf(1u, 2u) to Rational(18, 9), listOf(2u, 2u) to Rational(5, 2), - ).substituteFully(RationalField, bufferOf()) + ).substituteFully(RationalField, bufferOf()) } assertFailsWithTypeAndMessage( fullSubstitutionExceptionMessage, @@ -9200,37 +9201,2824 @@ class NumberedPolynomialUtilTest { listOf(1u, 2u) to Rational(-5, 5), listOf(2u, 2u) to Rational(-7, 8), ) - ).substituteFully(RationalField, bufferOf()) + ).substituteFully(RationalField, bufferOf()) } } @Test - @Ignore + @OptIn(UnstableKMathAPI::class) fun test_Polynomial_derivativeWithRespectTo_variable() { - // TODO + 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 - @Ignore + @OptIn(UnstableKMathAPI::class) fun test_Polynomial_nthDerivativeWithRespectTo_variable_order() { - // TODO + 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 - @Ignore + @OptIn(UnstableKMathAPI::class) fun test_Polynomial_nthDerivativeWithRespectTo_variablesAndOrders() { - // TODO + 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 - @Ignore + @OptIn(UnstableKMathAPI::class) fun test_Polynomial_antiderivativeWithRespectTo_variable() { - // TODO + 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 - @Ignore + @OptIn(UnstableKMathAPI::class) fun test_Polynomial_nthAntiderivativeWithRespectTo_variable_order() { - // TODO + 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 - @Ignore + @OptIn(UnstableKMathAPI::class) fun test_Polynomial_nthAntiderivativeWithRespectTo_variablesAndOrders() { - // TODO + 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 -- 2.34.1 From 5834fad938a973976eff3d0f1cea83df2198ba73 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Wed, 6 Jul 2022 00:37:46 +0300 Subject: [PATCH 118/275] Renamed constructing DSLs components. Fixed rejected NumberedPolynomial tests. --- .../kscience/kmath/functions/polynomials.kt | 205 +- .../kmath/functions/labeledConstructors.kt | 23 +- .../kmath/functions/numberedConstructors.kt | 22 +- .../functions/NumberedConstructorsTest.kt | 10 +- .../kmath/functions/NumberedPolynomialTest.kt | 2287 ++++++++--------- 5 files changed, 1270 insertions(+), 1277 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt index 273fe5cb9..7843a0210 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt @@ -8,6 +8,7 @@ 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 /** @@ -102,7 +103,7 @@ fun numberedPolynomialsExample() { numberedPolynomialSpace { // Also there is DSL for constructing NumberedPolynomials: - val polynomial5: NumberedPolynomial = NumberedPolynomial { + val polynomial5: NumberedPolynomial = NumberedPolynomialDSL1 { 3 {} 5 { 2 inPowerOf 1u } -7 with { 1 pow 2u; 3 pow 1u } @@ -116,7 +117,7 @@ fun numberedPolynomialsExample() { } } - val polynomial6: NumberedPolynomial = with(Int.algebra) { + val polynomial6: NumberedPolynomial = Int.algebra { NumberedPolynomial( listOf() to 7, listOf(0u, 1u) to -5, @@ -127,28 +128,28 @@ fun numberedPolynomialsExample() { // For every ring there can be provided a polynomial ring: Int.algebra.numberedPolynomialSpace { println( - -polynomial6 == NumberedPolynomial { - (-7) {} - 5 { 2 pow 1u } - 0 { 1 pow 2u; 3 pow 1u } - (-4) { 4 pow 4u } - } + -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 { - 10 {} - 0 { 2 pow 1u } - (-7) { 1 pow 2u; 3 pow 1u } - 4 { 4 pow 4u } - } + 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 { - (-4) {} - 10 { 2 pow 1u } - (-7) { 1 pow 2u; 3 pow 1u } - (-4) { 4 pow 4u } - } + 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 @@ -156,14 +157,14 @@ fun numberedPolynomialsExample() { Double.algebra.numberedPolynomialSpace { // You can even write - val x_1: NumberedPolynomial = NumberedPolynomial { 1.0 { 1 pow 1u } } - val x_2: NumberedPolynomial = NumberedPolynomial { 1.0 { 2 pow 1u } } - val x_3: NumberedPolynomial = NumberedPolynomial { 1.0 { 3 pow 1u } } - val polynomial7: NumberedPolynomial = NumberedPolynomial { - 3.0 {} - 5.0 { 2 pow 1u } - (-7.0) { 1 pow 2u; 3 pow 1u } - } + 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) @@ -171,49 +172,49 @@ fun numberedPolynomialsExample() { } Int.algebra.numberedPolynomialSpace { - val x_4: NumberedPolynomial = NumberedPolynomial { 1 { 4 pow 1u } } + 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 { - 3 {} - 5 { 4 pow 1u } - (-7) { 1 pow 2u; 3 pow 1u } - } + 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 { 5 {} } + 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 { - 2.0 {} - (-3.0) { 1 pow 1u } - 1.0 { 1 pow 2u } - }, - NumberedPolynomial { - 3.0 {} - (-1.0) { 1 pow 1u } - } + 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 { - 5.0 {} - (-4.0) { 1 pow 1u } - 1.0 { 1 pow 2u } - }, - NumberedPolynomial { - 3.0 {} - (-1.0) { 1 pow 1u } - } + 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 @@ -267,7 +268,7 @@ fun labeledPolynomialsExample() { labeledPolynomialSpace { // Also there is DSL for constructing NumberedPolynomials: - val polynomial5: LabeledPolynomial = LabeledPolynomial { + val polynomial5: LabeledPolynomial = LabeledPolynomialDSL1 { 3 {} 5 { y inPowerOf 1u } -7 with { x pow 2u; z pow 1u } @@ -281,7 +282,7 @@ fun labeledPolynomialsExample() { } } - val polynomial6: LabeledPolynomial = with(Int.algebra) { + val polynomial6: LabeledPolynomial = Int.algebra { LabeledPolynomial( mapOf() to 7, mapOf(y to 1u) to -5, @@ -292,28 +293,28 @@ fun labeledPolynomialsExample() { // For every ring there can be provided a polynomial ring: Int.algebra.labeledPolynomialSpace { println( - -polynomial6 == LabeledPolynomial { - (-7) {} - 5 { y pow 1u } - 0 { x pow 2u; z pow 1u } - (-4) { t pow 4u } - } + -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 { - 10 {} - 0 { y pow 1u } - (-7) { x pow 2u; z pow 1u } - 4 { t pow 4u } - } + 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 { - (-4) {} - 10 { y pow 1u } - (-7) { x pow 2u; z pow 1u } - (-4) { t pow 4u } - } + 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 @@ -321,11 +322,11 @@ fun labeledPolynomialsExample() { Double.algebra.labeledPolynomialSpace { // You can even write - val polynomial7: LabeledPolynomial = LabeledPolynomial { - 3.0 {} - 5.0 { y pow 1u } - (-7.0) { x pow 2u; z pow 1u } - } + 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) @@ -338,42 +339,42 @@ fun labeledPolynomialsExample() { // 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 { - 3 {} - 5 { t pow 1u } - (-7) { x pow 2u; z pow 1u } - } + 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 { 5 {} } + 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 { - 2.0 {} - (-3.0) { x pow 1u } - 1.0 { x pow 2u } - }, - LabeledPolynomial { - 3.0 {} - (-1.0) { x pow 1u } - } + 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 { - 5.0 {} - (-4.0) { x pow 1u } - 1.0 { x pow 2u } - }, - LabeledPolynomial { - 3.0 {} - (-1.0) { x pow 1u } - } + 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) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt index 7a8d961c0..8442d3f91 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt @@ -274,14 +274,14 @@ public inline fun C.asLabeledPolynomial() : LabeledPolynomial = LabeledPo */ @DslMarker @UnstableKMathAPI -internal annotation class LabeledPolynomialConstructorDSL +internal annotation class LabeledPolynomialConstructorDSL1 /** * Builder of [LabeledPolynomial] signature. It should be used as an implicit context for lambdas that describe term signature. */ @UnstableKMathAPI -@LabeledPolynomialConstructorDSL -public class LabeledPolynomialTermSignatureBuilder { +@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. @@ -302,7 +302,7 @@ public class LabeledPolynomialTermSignatureBuilder { * Declaring another power of the same variable will increase its degree by received degree. */ public infix fun Symbol.inPowerOf(deg: UInt) { - signature[this] = deg + signature[this] = signature.getOrElse(this) { 0u } + deg } /** * Declares power of [this] variable of degree [deg]. @@ -328,7 +328,8 @@ public class LabeledPolynomialTermSignatureBuilder { * Builder of [LabeledPolynomial]. It should be used as an implicit context for lambdas that describe [LabeledPolynomial]. */ @UnstableKMathAPI -public class LabeledPolynomialBuilder( +@LabeledPolynomialConstructorDSL1 +public class DSL1LabeledPolynomialBuilder( /** * Summation operation that will be used to sum coefficients of monomials of same signatures. */ @@ -367,15 +368,15 @@ public class LabeledPolynomialBuilder( * 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: LabeledPolynomialTermSignatureBuilder.() -> Unit): Unit = this.invoke(block) + 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: LabeledPolynomialTermSignatureBuilder.() -> Unit): Unit = - this with LabeledPolynomialTermSignatureBuilder().apply(block).build() + 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 @@ -398,7 +399,7 @@ public class LabeledPolynomialBuilder( // 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.LabeledPolynomial(initialCapacity: Int = 0, block: LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = LabeledPolynomialBuilder(::add, initialCapacity).apply(block).build() +//public inline fun > A.LabeledPolynomialDSL1(initialCapacity: Int = 0, block: LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = LabeledPolynomialBuilder(::add, initialCapacity).apply(block).build() /** * Creates [LabeledPolynomial] with lambda [block] in context of [this] ring of [LabeledPolynomial]s. * @@ -413,7 +414,7 @@ public class LabeledPolynomialBuilder( * ``` */ @UnstableKMathAPI -public inline fun > LabeledPolynomialSpace.LabeledPolynomial(initialCapacity: Int = 0, block: LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = LabeledPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build() +public inline fun > LabeledPolynomialSpace.LabeledPolynomialDSL1(initialCapacity: Int = 0, 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. * @@ -428,7 +429,7 @@ public inline fun > LabeledPolynomialSpace.LabeledPolynomial * ``` */ @UnstableKMathAPI -public inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(initialCapacity: Int = 0, block: LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = LabeledPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build() +public inline fun > LabeledRationalFunctionSpace.LabeledPolynomialDSL1(initialCapacity: Int = 0, block: DSL1LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = DSL1LabeledPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build() // Waiting for context receivers :( FIXME: Replace with context receivers when they will be available diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt index 7f02ff1e3..8d2c9e617 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt @@ -255,14 +255,14 @@ public inline fun C.asNumberedPolynomial() : NumberedPolynomial = Numbere */ @DslMarker @UnstableKMathAPI -internal annotation class NumberedPolynomialConstructorDSL +internal annotation class NumberedPolynomialConstructorDSL1 /** * Builder of [NumberedPolynomial] signature. It should be used as an implicit context for lambdas that describe term signature. */ @UnstableKMathAPI -@NumberedPolynomialConstructorDSL -public class NumberedPolynomialTermSignatureBuilder { +@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. @@ -316,8 +316,8 @@ public class NumberedPolynomialTermSignatureBuilder { * Builder of [NumberedPolynomial]. It should be used as an implicit context for lambdas that describe [NumberedPolynomial]. */ @UnstableKMathAPI -@NumberedPolynomialConstructorDSL -public class NumberedPolynomialBuilder( +@NumberedPolynomialConstructorDSL1 +public class DSL1NumberedPolynomialBuilder( /** * Summation operation that will be used to sum coefficients of monomials of same signatures. */ @@ -356,15 +356,15 @@ public class NumberedPolynomialBuilder( * 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: NumberedPolynomialTermSignatureBuilder.() -> Unit): Unit = this.invoke(block) + 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: NumberedPolynomialTermSignatureBuilder.() -> Unit): Unit = - this with NumberedPolynomialTermSignatureBuilder().apply(block).build() + 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 @@ -387,7 +387,7 @@ public class NumberedPolynomialBuilder( // 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.NumberedPolynomial(initialCapacity: Int = 0, block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder(::add, initialCapacity).apply(block).build() +//public inline fun > A.NumberedPolynomialDSL1(initialCapacity: Int = 0, block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder(::add, initialCapacity).apply(block).build() /** * Creates [NumberedPolynomial] with lambda [block] in context of [this] ring of [NumberedPolynomial]s. * @@ -402,7 +402,7 @@ public class NumberedPolynomialBuilder( * ``` */ @UnstableKMathAPI -public inline fun > NumberedPolynomialSpace.NumberedPolynomial(initialCapacity: Int = 0, block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build() +public inline fun > NumberedPolynomialSpace.NumberedPolynomialDSL1(initialCapacity: Int = 0, 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. * @@ -417,7 +417,7 @@ public inline fun > NumberedPolynomialSpace.NumberedPolynomi * ``` */ @UnstableKMathAPI -public inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(initialCapacity: Int = 0, block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build() +public inline fun > NumberedRationalFunctionSpace.NumberedPolynomialDSL1(initialCapacity: Int = 0, 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 diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt index 8d1b128cf..f9a5a041b 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt @@ -15,14 +15,14 @@ import kotlin.test.assertEquals class NumberedConstructorsTest { @Test @UnstableKMathAPI - fun testBuilder() { + fun testDSL1() { assertEquals( NumberedPolynomialAsIs( listOf(2u, 0u, 3u) to 5, listOf(0u, 1u) to -6, ), Int.algebra.numberedPolynomialSpace { - NumberedPolynomial { + NumberedPolynomialDSL1 { 5 { 1 pow 2u; 3 pow 3u } (-6) { 2 pow 1u } } @@ -34,7 +34,7 @@ class NumberedConstructorsTest { listOf() to -1, ), Int.algebra.numberedPolynomialSpace { - NumberedPolynomial { + NumberedPolynomialDSL1 { 5 { } (-6) { } } @@ -46,7 +46,7 @@ class NumberedConstructorsTest { listOf(2u) to -1, ), Int.algebra.numberedPolynomialSpace { - NumberedPolynomial { + NumberedPolynomialDSL1 { 5 { 1 pow 1u; 1 pow 1u } (-6) { 1 pow 2u } } @@ -58,7 +58,7 @@ class NumberedConstructorsTest { listOf(2u) to -1, ), Int.algebra.numberedPolynomialSpace { - NumberedPolynomial { + NumberedPolynomialDSL1 { 5 { 1 pow 1u; 1 pow 1u } (-6) { 1 pow 2u; 3 pow 0u } } diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt index dac7c1a62..f0a1128b4 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt @@ -14,84 +14,85 @@ import kotlin.test.* @UnstableKMathAPI class NumberedPolynomialTest { + private val o = Rational(0) @Test fun test_Polynomial_Int_plus() { RationalField.numberedPolynomialSpace { assertEquals( - NumberedPolynomial { - Rational(-22, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - NumberedPolynomial { - Rational(5, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } + -3, + 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 { - Rational(-3, 1) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - NumberedPolynomial { - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } + -3, + 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 { - Rational(0, 1) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - NumberedPolynomial { - Rational(27, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } + -3, + 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 { - Rational(0, 1) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - NumberedPolynomial { - Rational(27, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } + -3, + 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 { - Rational(-22, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } + 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 { - Rational(0, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } + 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 { - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } + val polynomial_7 = NumberedPolynomial( + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) assertSame( polynomial_7, polynomial_7 + 0, @@ -103,80 +104,80 @@ class NumberedPolynomialTest { fun test_Polynomial_Int_minus() { RationalField.numberedPolynomialSpace { assertEquals( - NumberedPolynomial { - Rational(-22, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - NumberedPolynomial { - Rational(5, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } - 3, + 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 { - Rational(-3, 1) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - NumberedPolynomial { - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } - 3, + 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 { - Rational(0, 1) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - NumberedPolynomial { - Rational(27, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } - 3, + 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 { - Rational(0, 1) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - NumberedPolynomial { - Rational(27, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } - 3, + 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 { - Rational(-22, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } + 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 { - Rational(0, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } + 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 { - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } + val polynomial_7 = NumberedPolynomial( + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) assertSame( polynomial_7, polynomial_7 - 0, @@ -188,46 +189,46 @@ class NumberedPolynomialTest { fun test_Polynomial_Int_times() { IntModuloRing(35).numberedPolynomialSpace { assertEquals( - NumberedPolynomial { - m(34) with {} - m(2) with { 1 pow 3u } - m(1) with { 2 pow 1u } - m(20) with { 1 pow 1u } - m(2) with { 3 pow 2u } - }, - NumberedPolynomial { - m(22) with {} - m(26) with { 1 pow 3u } - m(13) with { 2 pow 1u } - m(15) with { 1 pow 1u } - m(26) with { 3 pow 2u } - } * 27, + 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 { - m(0) with {} - m(0) with { 1 pow 3u } - m(0) with { 2 pow 1u } - m(0) with { 1 pow 1u } - m(0) with { 3 pow 2u } - }, - NumberedPolynomial { - m(7) with {} - m(0) with { 1 pow 3u } - m(49) with { 2 pow 1u } - m(21) with { 1 pow 1u } - m(14) with { 3 pow 2u } - } * 15, + 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 { - m(22) with {} - m(26) with { 1 pow 3u } - m(13) with { 2 pow 1u } - m(15) with { 1 pow 1u } - m(26) with { 3 pow 2u } - } + 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, @@ -244,80 +245,80 @@ class NumberedPolynomialTest { fun test_Int_Polynomial_plus() { RationalField.numberedPolynomialSpace { assertEquals( - NumberedPolynomial { - Rational(-22, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - -3 + NumberedPolynomial { - Rational(5, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, + 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 { - Rational(-3, 1) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - -3 + NumberedPolynomial { - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, + 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 { - Rational(0, 1) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - -3 + NumberedPolynomial { - Rational(27, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, + 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 { - Rational(0, 1) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - -3 + NumberedPolynomial { - Rational(27, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, + 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 { - Rational(-22, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } + 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 { - Rational(0, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } + 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 { - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } + val polynomial_7 = NumberedPolynomial( + listOf(3u) to Rational(-8, 9), + listOf(0u, 4u) to Rational(-8, 7), + ) assertSame( polynomial_7, 0 + polynomial_7, @@ -329,91 +330,91 @@ class NumberedPolynomialTest { fun test_Int_Polynomial_minus() { RationalField.numberedPolynomialSpace { assertEquals( - NumberedPolynomial { - Rational(22, 9) with {} - Rational(8, 9) with { 1 pow 3u } - Rational(8, 7) with { 2 pow 4u } - }, - 3 - NumberedPolynomial { - Rational(5, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, + 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 { - Rational(3, 1) with {} - Rational(8, 9) with { 1 pow 3u } - Rational(8, 7) with { 2 pow 4u } - }, - 3 - NumberedPolynomial { - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, + 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 { - Rational(0, 1) with {} - Rational(8, 9) with { 1 pow 3u } - Rational(8, 7) with { 2 pow 4u } - }, - 3 - NumberedPolynomial { - Rational(27, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, + 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 { - Rational(0, 1) with {} - Rational(8, 9) with { 1 pow 3u } - Rational(8, 7) with { 2 pow 4u } - }, - 3 - NumberedPolynomial { - Rational(27, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, + 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 { - Rational(22, 9) with {} - Rational(8, 9) with { 1 pow 3u } - Rational(8, 7) with { 2 pow 4u } - }, - 0 - NumberedPolynomial { - Rational(-22, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, + 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 { - Rational(0, 9) with {} - Rational(8, 9) with { 1 pow 3u } - Rational(8, 7) with { 2 pow 4u } - }, - 0 - NumberedPolynomial { - Rational(0, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, + 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 { - Rational(8, 9) with { 1 pow 3u } - Rational(8, 7) with { 2 pow 4u } - }, - 0 - NumberedPolynomial { - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, + 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" ) } @@ -422,46 +423,46 @@ class NumberedPolynomialTest { fun test_Int_Polynomial_times() { IntModuloRing(35).numberedPolynomialSpace { assertEquals( - NumberedPolynomial { - m(34) with {} - m(2) with { 1 pow 3u } - m(1) with { 2 pow 1u } - m(20) with { 1 pow 1u } - m(2) with { 3 pow 2u } - }, - 27 * NumberedPolynomial { - m(22) with {} - m(26) with { 1 pow 3u } - m(13) with { 2 pow 1u } - m(15) with { 1 pow 1u } - m(26) with { 3 pow 2u } - }, + 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 { - m(0) with {} - m(0) with { 1 pow 3u } - m(0) with { 2 pow 1u } - m(0) with { 1 pow 1u } - m(0) with { 3 pow 2u } - }, - 15 * NumberedPolynomial { - m(7) with {} - m(0) with { 1 pow 3u } - m(49) with { 2 pow 1u } - m(21) with { 1 pow 1u } - m(14) with { 3 pow 2u } - }, + 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 { - m(22) with {} - m(26) with { 1 pow 3u } - m(13) with { 2 pow 1u } - m(15) with { 1 pow 1u } - m(26) with { 3 pow 2u } - } + 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, @@ -478,92 +479,91 @@ class NumberedPolynomialTest { fun test_Polynomial_Constant_plus() { RationalField.numberedPolynomialSpace { assertEquals( - NumberedPolynomial { - Rational(-22, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - NumberedPolynomial { - Rational(5, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } + Rational(-3), + 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 { - Rational(-3, 1) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - NumberedPolynomial { - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } + Rational(-3), + 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 { - Rational(0, 1) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - NumberedPolynomial { - Rational(27, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } + Rational(-3), + 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 { - Rational(0, 1) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - NumberedPolynomial { - Rational(27, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } + Rational(-3), + 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 { - Rational(-22, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - NumberedPolynomial { - Rational(-22, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } + Rational(0), + 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 { - Rational(0, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - NumberedPolynomial { - Rational(0, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } + Rational(0), + 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 { - Rational(0) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - NumberedPolynomial { - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } + Rational(0), + NumberedPolynomial( + 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" ) } @@ -572,92 +572,91 @@ class NumberedPolynomialTest { fun test_Polynomial_Constant_minus() { RationalField.numberedPolynomialSpace { assertEquals( - NumberedPolynomial { - Rational(-22, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - NumberedPolynomial { - Rational(5, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } - Rational(3), + 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 { - Rational(-3, 1) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - NumberedPolynomial { - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } - Rational(3), + 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 { - Rational(0, 1) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - NumberedPolynomial { - Rational(27, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } - Rational(3), + 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 { - Rational(0, 1) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - NumberedPolynomial { - Rational(27, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } - Rational(3), + 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 { - Rational(-22, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - NumberedPolynomial { - Rational(-22, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } - Rational(0), + 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 { - Rational(0, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - NumberedPolynomial { - Rational(0, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } - Rational(0), + 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 { - Rational(0) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - NumberedPolynomial { - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - } - Rational(0), + NumberedPolynomial( + 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" ) } @@ -666,71 +665,71 @@ class NumberedPolynomialTest { fun test_Polynomial_Constant_times() { IntModuloRing(35).numberedPolynomialSpace { assertEquals( - NumberedPolynomial { - m(34) with {} - m(2) with { 1 pow 3u } - m(1) with { 2 pow 1u } - m(20) with { 1 pow 1u } - m(2) with { 3 pow 2u } - }, - NumberedPolynomial { - m(22) with {} - m(26) with { 1 pow 3u } - m(13) with { 2 pow 1u } - m(15) with { 1 pow 1u } - m(26) with { 3 pow 2u } - } * m(27), + 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 { - m(0) with {} - m(0) with { 1 pow 3u } - m(0) with { 2 pow 1u } - m(0) with { 1 pow 1u } - m(0) with { 3 pow 2u } - }, - NumberedPolynomial { - m(7) with {} - m(0) with { 1 pow 3u } - m(49) with { 2 pow 1u } - m(21) with { 1 pow 1u } - m(14) with { 3 pow 2u } - } * m(15), + 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 { - m(0) with {} - m(0) with { 1 pow 3u } - m(0) with { 2 pow 1u } - m(0) with { 1 pow 1u } - m(0) with { 3 pow 2u } - }, - NumberedPolynomial { - m(22) with {} - m(26) with { 1 pow 3u } - m(13) with { 2 pow 1u } - m(15) with { 1 pow 1u } - m(26) with { 3 pow 2u } - } * m(0), + 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 { - m(22) with {} - m(26) with { 1 pow 3u } - m(13) with { 2 pow 1u } - m(15) with { 1 pow 1u } - m(26) with { 3 pow 2u } - }, - NumberedPolynomial { - m(22) with {} - m(26) with { 1 pow 3u } - m(13) with { 2 pow 1u } - m(15) with { 1 pow 1u } - m(26) with { 3 pow 2u } - } * 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), + ), + 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" ) } @@ -739,92 +738,91 @@ class NumberedPolynomialTest { fun test_Constant_Polynomial_plus() { RationalField.numberedPolynomialSpace { assertEquals( - NumberedPolynomial { - Rational(-22, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - Rational(-3) + NumberedPolynomial { - Rational(5, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, + 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 { - Rational(-3, 1) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - Rational(-3) + NumberedPolynomial { - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, + 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 { - Rational(0, 1) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - Rational(-3) + NumberedPolynomial { - Rational(27, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, + 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 { - Rational(0, 1) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - Rational(-3) + NumberedPolynomial { - Rational(27, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, + 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 { - Rational(-22, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - Rational(0) + NumberedPolynomial { - Rational(-22, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, + 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 { - Rational(0, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - Rational(0) + NumberedPolynomial { - Rational(0, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, + 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 { - Rational(0) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, - Rational(0) + NumberedPolynomial { - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, + NumberedPolynomial( + 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" ) } @@ -833,92 +831,92 @@ class NumberedPolynomialTest { fun test_Constant_Polynomial_minus() { RationalField.numberedPolynomialSpace { assertEquals( - NumberedPolynomial { - Rational(22, 9) with {} - Rational(8, 9) with { 1 pow 3u } - Rational(8, 7) with { 2 pow 4u } - }, - Rational(3) - NumberedPolynomial { - Rational(5, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, + 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 { - Rational(3, 1) with {} - Rational(8, 9) with { 1 pow 3u } - Rational(8, 7) with { 2 pow 4u } - }, - Rational(3) - NumberedPolynomial { - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, + 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 { - Rational(0, 1) with {} - Rational(8, 9) with { 1 pow 3u } - Rational(8, 7) with { 2 pow 4u } - }, - Rational(3) - NumberedPolynomial { - Rational(27, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, + 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 { - Rational(0, 1) with {} - Rational(8, 9) with { 1 pow 3u } - Rational(8, 7) with { 2 pow 4u } - }, - Rational(3) - NumberedPolynomial { - Rational(27, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, + 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 { - Rational(22, 9) with {} - Rational(8, 9) with { 1 pow 3u } - Rational(8, 7) with { 2 pow 4u } - }, - Rational(0) - NumberedPolynomial { - Rational(-22, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, + 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 { - Rational(0, 9) with {} - Rational(8, 9) with { 1 pow 3u } - Rational(8, 7) with { 2 pow 4u } - }, - Rational(0) - NumberedPolynomial { - Rational(0, 9) with {} - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, + 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 { - Rational(0) with {} - Rational(8, 9) with { 1 pow 3u } - Rational(8, 7) with { 2 pow 4u } - }, - Rational(0) - NumberedPolynomial { - Rational(-8, 9) with { 1 pow 3u } - Rational(-8, 7) with { 2 pow 4u } - }, + 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" ) } @@ -927,71 +925,71 @@ class NumberedPolynomialTest { fun test_Constant_Polynomial_times() { IntModuloRing(35).numberedPolynomialSpace { assertEquals( - NumberedPolynomial { - m(34) with {} - m(2) with { 1 pow 3u } - m(1) with { 2 pow 1u } - m(20) with { 1 pow 1u } - m(2) with { 3 pow 2u } - }, - m(27) * NumberedPolynomial { - m(22) with {} - m(26) with { 1 pow 3u } - m(13) with { 2 pow 1u } - m(15) with { 1 pow 1u } - m(26) with { 3 pow 2u } - }, + 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 { - m(0) with {} - m(0) with { 1 pow 3u } - m(0) with { 2 pow 1u } - m(0) with { 1 pow 1u } - m(0) with { 3 pow 2u } - }, - m(15) * NumberedPolynomial { - m(7) with {} - m(0) with { 1 pow 3u } - m(49) with { 2 pow 1u } - m(21) with { 1 pow 1u } - m(14) with { 3 pow 2u } - }, + 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 { - m(0) with {} - m(0) with { 1 pow 3u } - m(0) with { 2 pow 1u } - m(0) with { 1 pow 1u } - m(0) with { 3 pow 2u } - }, - m(0) * NumberedPolynomial { - m(22) with {} - m(26) with { 1 pow 3u } - m(13) with { 2 pow 1u } - m(15) with { 1 pow 1u } - m(26) with { 3 pow 2u } - }, + 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 { - m(22) with {} - m(26) with { 1 pow 3u } - m(13) with { 2 pow 1u } - m(15) with { 1 pow 1u } - m(26) with { 3 pow 2u } - }, - m(1) * NumberedPolynomial { - m(22) with {} - m(26) with { 1 pow 3u } - m(13) with { 2 pow 1u } - m(15) with { 1 pow 1u } - m(26) with { 3 pow 2u } - }, + 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" ) } @@ -1000,33 +998,33 @@ class NumberedPolynomialTest { fun test_Polynomial_unaryMinus() { RationalField.numberedPolynomialSpace { assertEquals( - NumberedPolynomial { - Rational(-5, 9) with { 1 pow 5u } - Rational(8, 9) with {} - Rational(8, 7) with { 7 pow 13u } - }, - -NumberedPolynomial { - Rational(5, 9) with { 1 pow 5u } - Rational(-8, 9) with {} - Rational(-8, 7) with { 7 pow 13u } - }, + 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 { - Rational(-5, 9) with { 3 pow 7u } - Rational(8, 9) with {} - Rational(8, 7) with { 1 pow 3u } - Rational(0) with { 2 pow 4u } - Rational(0) with { 1 pow 5u } - }, - -NumberedPolynomial { - Rational(5, 9) with { 3 pow 7u } - Rational(-8, 9) with {} - Rational(-8, 7) with { 1 pow 3u } - Rational(0) with { 2 pow 4u } - Rational(0) with { 1 pow 5u } - }, + 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" ) } @@ -1035,137 +1033,137 @@ class NumberedPolynomialTest { fun test_Polynomial_Polynomial_plus() { RationalField.numberedPolynomialSpace { assertEquals( - NumberedPolynomial { - Rational(-17, 2) with {} - Rational(-1, 3) with { 1 pow 1u } - Rational(-25, 21) with { 1 pow 2u } - Rational(146, 63) with { 2 pow 1u } - Rational(-3, 5) with { 1 pow 1u; 2 pow 1u } - Rational(61, 15) with { 1 pow 2u; 2 pow 1u } - Rational(157, 63) with { 2 pow 2u } - Rational(-55, 21) with { 1 pow 1u; 2 pow 2u } - Rational(11, 24) with { 1 pow 2u; 2 pow 2u } - }, - NumberedPolynomial { - Rational(6, 4) with {} - Rational(-2, 6) with { 1 pow 1u } - Rational(10, 6) with { 1 pow 2u } - Rational(17, 7) with { 2 pow 1u } - Rational(-7, 7) with { 1 pow 1u; 2 pow 1u } - Rational(12, 5) with { 1 pow 2u; 2 pow 1u } - Rational(12, 7) with { 2 pow 2u } - Rational(-10, 3) with { 1 pow 1u; 2 pow 2u } - Rational(9, 8) with { 1 pow 2u; 2 pow 2u } - } + NumberedPolynomial { - Rational(-20, 2) with {} - Rational(0, 9) with { 1 pow 1u } - Rational(-20, 7) with { 1 pow 2u } - Rational(-1, 9) with { 2 pow 1u } - Rational(2, 5) with { 1 pow 1u; 2 pow 1u } - Rational(10, 6) with { 1 pow 2u; 2 pow 1u } - Rational(7, 9) with { 2 pow 2u } - Rational(5, 7) with { 1 pow 1u; 2 pow 2u } - Rational(-2, 3) with { 1 pow 2u; 2 pow 2u } - }, + 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 { - Rational(-17, 2) with {} - Rational(-1, 3) with { 1 pow 1u } - Rational(-25, 21) with { 1 pow 2u } - Rational(-1, 9) with { 2 pow 1u } - Rational(2, 5) with { 1 pow 1u; 2 pow 1u } - Rational(10, 6) with { 1 pow 2u; 2 pow 1u } - Rational(157, 63) with { 2 pow 2u } - Rational(-55, 21) with { 1 pow 1u; 2 pow 2u } - Rational(11, 24) with { 1 pow 2u; 2 pow 2u } - }, - NumberedPolynomial { - Rational(6, 4) with {} - Rational(-2, 6) with { 1 pow 1u } - Rational(10, 6) with { 1 pow 2u } - Rational(12, 7) with { 2 pow 2u } - Rational(-10, 3) with { 1 pow 1u; 2 pow 2u } - Rational(9, 8) with { 1 pow 2u; 2 pow 2u } - } + NumberedPolynomial { - Rational(-20, 2) with {} - Rational(0, 9) with { 1 pow 1u } - Rational(-20, 7) with { 1 pow 2u } - Rational(-1, 9) with { 2 pow 1u } - Rational(2, 5) with { 1 pow 1u; 2 pow 1u } - Rational(10, 6) with { 1 pow 2u; 2 pow 1u } - Rational(7, 9) with { 2 pow 2u } - Rational(5, 7) with { 1 pow 1u; 2 pow 2u } - Rational(-2, 3) with { 1 pow 2u; 2 pow 2u } - }, + 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 { - Rational(-17, 2) with {} - Rational(-1, 3) with { 1 pow 1u } - Rational(-25, 21) with { 1 pow 2u } - Rational(-1, 9) with { 2 pow 1u } - Rational(2, 5) with { 1 pow 1u; 2 pow 1u } - Rational(10, 6) with { 1 pow 2u; 2 pow 1u } - Rational(12, 7) with { 2 pow 2u } - Rational(-10, 3) with { 1 pow 1u; 2 pow 2u } - Rational(9, 8) with { 1 pow 2u; 2 pow 2u } - }, - NumberedPolynomial { - Rational(6, 4) with {} - Rational(-2, 6) with { 1 pow 1u } - Rational(10, 6) with { 1 pow 2u } - Rational(12, 7) with { 2 pow 2u } - Rational(-10, 3) with { 1 pow 1u; 2 pow 2u } - Rational(9, 8) with { 1 pow 2u; 2 pow 2u } - } + NumberedPolynomial { - Rational(-20, 2) with {} - Rational(0, 9) with { 1 pow 1u } - Rational(-20, 7) with { 1 pow 2u } - Rational(-1, 9) with { 2 pow 1u } - Rational(2, 5) with { 1 pow 1u; 2 pow 1u } - Rational(10, 6) with { 1 pow 2u; 2 pow 1u } - Rational(0) with { 2 pow 2u } - Rational(0) with { 1 pow 1u; 2 pow 2u } - Rational(0) with { 1 pow 2u; 2 pow 2u } - }, + 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 { - Rational(0) with {} - Rational(0) with { 1 pow 1u } - Rational(0) with { 1 pow 2u } - Rational(0) with { 2 pow 1u } - Rational(0) with { 1 pow 1u; 2 pow 1u } - Rational(0) with { 1 pow 2u; 2 pow 1u } - Rational(0) with { 2 pow 2u } - Rational(0) with { 1 pow 1u; 2 pow 2u } - Rational(0) with { 1 pow 2u; 2 pow 2u } - }, - NumberedPolynomial { - Rational(6, 4) with {} - Rational(-2, 6) with { 1 pow 1u } - Rational(10, 6) with { 1 pow 2u } - Rational(17, 7) with { 2 pow 1u } - Rational(-7, 7) with { 1 pow 1u; 2 pow 1u } - Rational(12, 5) with { 1 pow 2u; 2 pow 1u } - Rational(12, 7) with { 2 pow 2u } - Rational(-10, 3) with { 1 pow 1u; 2 pow 2u } - Rational(9, 8) with { 1 pow 2u; 2 pow 2u } - } + NumberedPolynomial { - Rational(-6, 4) with {} - Rational(2, 6) with { 1 pow 1u } - Rational(-10, 6) with { 1 pow 2u } - Rational(-17, 7) with { 2 pow 1u } - Rational(7, 7) with { 1 pow 1u; 2 pow 1u } - Rational(-12, 5) with { 1 pow 2u; 2 pow 1u } - Rational(-12, 7) with { 2 pow 2u } - Rational(10, 3) with { 1 pow 1u; 2 pow 2u } - Rational(-9, 8) with { 1 pow 2u; 2 pow 2u } - }, + 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" ) } @@ -1174,137 +1172,137 @@ class NumberedPolynomialTest { fun test_Polynomial_Polynomial_minus() { RationalField.numberedPolynomialSpace { assertEquals( - NumberedPolynomial { - Rational(-17, 2) with {} - Rational(-1, 3) with { 1 pow 1u } - Rational(-25, 21) with { 1 pow 2u } - Rational(146, 63) with { 2 pow 1u } - Rational(-3, 5) with { 1 pow 1u; 2 pow 1u } - Rational(61, 15) with { 1 pow 2u; 2 pow 1u } - Rational(157, 63) with { 2 pow 2u } - Rational(-55, 21) with { 1 pow 1u; 2 pow 2u } - Rational(11, 24) with { 1 pow 2u; 2 pow 2u } - }, - NumberedPolynomial { - Rational(6, 4) with {} - Rational(-2, 6) with { 1 pow 1u } - Rational(10, 6) with { 1 pow 2u } - Rational(17, 7) with { 2 pow 1u } - Rational(-7, 7) with { 1 pow 1u; 2 pow 1u } - Rational(12, 5) with { 1 pow 2u; 2 pow 1u } - Rational(12, 7) with { 2 pow 2u } - Rational(-10, 3) with { 1 pow 1u; 2 pow 2u } - Rational(9, 8) with { 1 pow 2u; 2 pow 2u } - } - NumberedPolynomial { - Rational(20, 2) with {} - Rational(0, 9) with { 1 pow 1u } - Rational(20, 7) with { 1 pow 2u } - Rational(1, 9) with { 2 pow 1u } - Rational(-2, 5) with { 1 pow 1u; 2 pow 1u } - Rational(-10, 6) with { 1 pow 2u; 2 pow 1u } - Rational(-7, 9) with { 2 pow 2u } - Rational(-5, 7) with { 1 pow 1u; 2 pow 2u } - Rational(2, 3) with { 1 pow 2u; 2 pow 2u } - }, + 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 { - Rational(-17, 2) with {} - Rational(-1, 3) with { 1 pow 1u } - Rational(-25, 21) with { 1 pow 2u } - Rational(-1, 9) with { 2 pow 1u } - Rational(2, 5) with { 1 pow 1u; 2 pow 1u } - Rational(10, 6) with { 1 pow 2u; 2 pow 1u } - Rational(157, 63) with { 2 pow 2u } - Rational(-55, 21) with { 1 pow 1u; 2 pow 2u } - Rational(11, 24) with { 1 pow 2u; 2 pow 2u } - }, - NumberedPolynomial { - Rational(6, 4) with {} - Rational(-2, 6) with { 1 pow 1u } - Rational(10, 6) with { 1 pow 2u } - Rational(12, 7) with { 2 pow 2u } - Rational(-10, 3) with { 1 pow 1u; 2 pow 2u } - Rational(9, 8) with { 1 pow 2u; 2 pow 2u } - } - NumberedPolynomial { - Rational(20, 2) with {} - Rational(0, 9) with { 1 pow 1u } - Rational(20, 7) with { 1 pow 2u } - Rational(1, 9) with { 2 pow 1u } - Rational(-2, 5) with { 1 pow 1u; 2 pow 1u } - Rational(-10, 6) with { 1 pow 2u; 2 pow 1u } - Rational(-7, 9) with { 2 pow 2u } - Rational(-5, 7) with { 1 pow 1u; 2 pow 2u } - Rational(2, 3) with { 1 pow 2u; 2 pow 2u } - }, + 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 { - Rational(-17, 2) with {} - Rational(-1, 3) with { 1 pow 1u } - Rational(-25, 21) with { 1 pow 2u } - Rational(-1, 9) with { 2 pow 1u } - Rational(2, 5) with { 1 pow 1u; 2 pow 1u } - Rational(10, 6) with { 1 pow 2u; 2 pow 1u } - Rational(12, 7) with { 2 pow 2u } - Rational(-10, 3) with { 1 pow 1u; 2 pow 2u } - Rational(9, 8) with { 1 pow 2u; 2 pow 2u } - }, - NumberedPolynomial { - Rational(6, 4) with {} - Rational(-2, 6) with { 1 pow 1u } - Rational(10, 6) with { 1 pow 2u } - Rational(12, 7) with { 2 pow 2u } - Rational(-10, 3) with { 1 pow 1u; 2 pow 2u } - Rational(9, 8) with { 1 pow 2u; 2 pow 2u } - } - NumberedPolynomial { - Rational(20, 2) with {} - Rational(0, 9) with { 1 pow 1u } - Rational(20, 7) with { 1 pow 2u } - Rational(1, 9) with { 2 pow 1u } - Rational(-2, 5) with { 1 pow 1u; 2 pow 1u } - Rational(-10, 6) with { 1 pow 2u; 2 pow 1u } - Rational(0) with { 2 pow 2u } - Rational(0) with { 1 pow 1u; 2 pow 2u } - Rational(0) with { 1 pow 2u; 2 pow 2u } - }, + 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 { - Rational(0) with {} - Rational(0) with { 1 pow 1u } - Rational(0) with { 1 pow 2u } - Rational(0) with { 2 pow 1u } - Rational(0) with { 1 pow 1u; 2 pow 1u } - Rational(0) with { 1 pow 2u; 2 pow 1u } - Rational(0) with { 2 pow 2u } - Rational(0) with { 1 pow 1u; 2 pow 2u } - Rational(0) with { 1 pow 2u; 2 pow 2u } - }, - NumberedPolynomial { - Rational(6, 4) with {} - Rational(-2, 6) with { 1 pow 1u } - Rational(10, 6) with { 1 pow 2u } - Rational(17, 7) with { 2 pow 1u } - Rational(-7, 7) with { 1 pow 1u; 2 pow 1u } - Rational(12, 5) with { 1 pow 2u; 2 pow 1u } - Rational(12, 7) with { 2 pow 2u } - Rational(-10, 3) with { 1 pow 1u; 2 pow 2u } - Rational(9, 8) with { 1 pow 2u; 2 pow 2u } - } - NumberedPolynomial { - Rational(6, 4) with {} - Rational(-2, 6) with { 1 pow 1u } - Rational(10, 6) with { 1 pow 2u } - Rational(17, 7) with { 2 pow 1u } - Rational(-7, 7) with { 1 pow 1u; 2 pow 1u } - Rational(12, 5) with { 1 pow 2u; 2 pow 1u } - Rational(12, 7) with { 2 pow 2u } - Rational(-10, 3) with { 1 pow 1u; 2 pow 2u } - Rational(9, 8) with { 1 pow 2u; 2 pow 2u } - }, + 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" ) } @@ -1314,255 +1312,250 @@ class NumberedPolynomialTest { IntModuloRing(35).numberedPolynomialSpace { // (p + q + r) * (p^2 + q^2 + r^2 - pq - pr - qr) = p^3 + q^3 + r^3 - 3pqr assertEquals( - NumberedPolynomial { - m(1) with { 1 pow 3u } - m(1) with { 2 pow 3u } - m(1) with { 3 pow 3u } - m(0) with { 1 pow 1u; 2 pow 2u } - m(0) with { 2 pow 1u; 3 pow 2u } - m(0) with { 3 pow 1u; 1 pow 2u } - m(0) with { 1 pow 1u; 3 pow 2u } - m(0) with { 2 pow 1u; 1 pow 2u } - m(0) with { 3 pow 1u; 2 pow 2u } - m(-3) with { 1 pow 1u; 2 pow 1u; 3 pow 1u } - }, - NumberedPolynomial { - m(1) with { 1 pow 1u } - m(1) with { 2 pow 1u } - m(1) with { 3 pow 1u } - } * NumberedPolynomial { - m(1) with { 1 pow 2u } - m(1) with { 2 pow 2u } - m(1) with { 3 pow 2u } - m(-1) with { 1 pow 1u; 2 pow 1u } - m(-1) with { 2 pow 1u; 3 pow 1u } - m(-1) with { 3 pow 1u; 1 pow 1u } - }, + 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 { - m(0) with { 1 pow 2u } - m(0) with { 2 pow 2u } - m(0) with { 3 pow 2u } - m(0) with { 1 pow 1u; 2 pow 1u } - m(0) with { 2 pow 1u; 3 pow 1u } - m(0) with { 3 pow 1u; 1 pow 1u } - }, - NumberedPolynomial { - m(5) with { 1 pow 1u } - m(-25) with { 2 pow 1u } - m(10) with { 3 pow 1u } - } * NumberedPolynomial { - m(21) with { 1 pow 1u } - m(14) with { 2 pow 1u } - m(-7) with { 3 pow 1u } - }, + 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() { - val o = Rational(0) RationalField.numberedPolynomialSpace { assertEquals( -1, - NumberedPolynomial {}.lastVariable, + NumberedPolynomial().lastVariable, "test 1" ) assertEquals( -1, - NumberedPolynomial { - o {} - }.lastVariable, + NumberedPolynomial( + listOf() to o + ).lastVariable, "test 2" ) assertEquals( 2, - NumberedPolynomial { - o { 1 pow 1u; 2 pow 2u; 3 pow 3u } - }.lastVariable, + NumberedPolynomial( + listOf(1u, 2u, 3u) to o + ).lastVariable, "test 3" ) assertEquals( 3, - NumberedPolynomial { - o { 1 pow 0u; 2 pow 1u; 3 pow 2u; 4 pow 1u; 5 pow 0u } - }.also { println(it) }.lastVariable, + NumberedPolynomial( + listOf(0u, 1u, 2u, 1u, 0u) to o + ).also { println(it) }.lastVariable, "test 4" ) assertEquals( 2, - NumberedPolynomial { - o {} - o { 2 pow 1u } - o { 1 pow 2u; 3 pow 1u } - }.lastVariable, + NumberedPolynomial( + listOf() to o, + listOf(0u, 1u) to o, + listOf(2u, 0u, 1u) to o, + ).lastVariable, "test 5" ) } } @Test fun test_degree() { - val o = Rational(0) RationalField.numberedPolynomialSpace { assertEquals( -1, - NumberedPolynomial {}.degree, + NumberedPolynomial().degree, "test 1" ) assertEquals( 0, - NumberedPolynomial { - o {} - }.degree, + NumberedPolynomial( + listOf() to o + ).degree, "test 2" ) assertEquals( 6, - NumberedPolynomial { - o { 1 pow 1u; 2 pow 2u; 3 pow 3u } - }.degree, + NumberedPolynomial( + listOf(1u, 2u, 3u) to o + ).degree, "test 3" ) assertEquals( 4, - NumberedPolynomial { - o { 1 pow 0u; 2 pow 1u; 3 pow 2u; 4 pow 1u; 5 pow 0u } - }.degree, + NumberedPolynomial( + listOf(0u, 1u, 2u, 1u, 0u) to o + ).degree, "test 4" ) assertEquals( 3, - NumberedPolynomial { - o {} - o { 2 pow 1u } - o { 1 pow 2u; 3 pow 1u } - }.degree, + NumberedPolynomial( + listOf() to o, + listOf(0u, 1u) to o, + listOf(2u, 0u, 1u) to o, + ).degree, "test 5" ) assertEquals( 4, - NumberedPolynomial { - o {} - o { 2 pow 1u } - o { 1 pow 2u; 3 pow 1u } - o { 4 pow 4u } - }.degree, + 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() { - val o = Rational(0) RationalField.numberedPolynomialSpace { assertEquals( listOf(), - NumberedPolynomial {}.degrees, + NumberedPolynomial().degrees, "test 1" ) assertEquals( listOf(), - NumberedPolynomial { - o {} - }.degrees, + NumberedPolynomial( + listOf() to o + ).degrees, "test 2" ) assertEquals( listOf(1u, 2u, 3u), - NumberedPolynomial { - o { 1 pow 1u; 2 pow 2u; 3 pow 3u } - }.degrees, + NumberedPolynomial( + listOf(1u, 2u, 3u) to o + ).degrees, "test 3" ) assertEquals( listOf(0u, 1u, 2u, 1u), - NumberedPolynomial { - o { 1 pow 0u; 2 pow 1u; 3 pow 2u; 4 pow 1u; 5 pow 0u } - }.degrees, + NumberedPolynomial( + listOf(0u, 1u, 2u, 1u, 0u) to o + ).degrees, "test 4" ) assertEquals( listOf(2u, 1u, 1u), - NumberedPolynomial { - o {} - o { 2 pow 1u } - o { 1 pow 2u; 3 pow 1u } - }.degrees, + 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 { - o {} - o { 1 pow 1u; 2 pow 2u } - o { 2 pow 1u; 3 pow 2u } - o { 1 pow 2u; 3 pow 1u } - o { 4 pow 4u } - }.degrees, + 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() { - val o = Rational(0) RationalField.numberedPolynomialSpace { fun NumberedPolynomial.collectDegrees(limit: Int = lastVariable + 2): List = List(limit) { degreeBy(it) } assertEquals( listOf(0u), - NumberedPolynomial {}.collectDegrees(), + NumberedPolynomial().collectDegrees(), "test 1" ) assertEquals( listOf(0u), - NumberedPolynomial { - o {} - }.collectDegrees(), + NumberedPolynomial( + listOf() to o + ).collectDegrees(), "test 2" ) assertEquals( listOf(1u, 2u, 3u, 0u), - NumberedPolynomial { - o { 1 pow 1u; 2 pow 2u; 3 pow 3u } - }.collectDegrees(), + NumberedPolynomial( + listOf(1u, 2u, 3u) to o + ).collectDegrees(), "test 3" ) assertEquals( listOf(0u, 1u, 2u, 1u, 0u), - NumberedPolynomial { - o { 1 pow 0u; 2 pow 1u; 3 pow 2u; 4 pow 1u; 5 pow 0u } - }.collectDegrees(), + NumberedPolynomial( + listOf(0u, 1u, 2u, 1u, 0u) to o + ).collectDegrees(), "test 4" ) assertEquals( listOf(2u, 1u, 1u, 0u), - NumberedPolynomial { - o {} - o { 2 pow 1u } - o { 1 pow 2u; 3 pow 1u } - }.collectDegrees(), + 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 { - o {} - o { 1 pow 1u; 2 pow 2u } - o { 2 pow 1u; 3 pow 2u } - o { 1 pow 2u; 3 pow 1u } - o { 4 pow 4u } - }.collectDegrees(), + 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() { - val o = Rational(0) RationalField.numberedPolynomialSpace { fun NumberedPolynomial.checkDegreeBy(message: String? = null) { val lastVariable = lastVariable @@ -1587,153 +1580,151 @@ class NumberedPolynomialTest { fail("${message ?: ""} Incorrect answer for variable collection $indexCollection: expected $expected, actual $actual") } } - NumberedPolynomial {}.checkDegreeBy("test 1") - NumberedPolynomial { - o {} - }.checkDegreeBy("test 2") - NumberedPolynomial { - o { 1 pow 1u; 2 pow 2u; 3 pow 3u } - }.checkDegreeBy("test 3") - NumberedPolynomial { - o { 1 pow 0u; 2 pow 1u; 3 pow 2u; 4 pow 1u; 5 pow 0u } - }.checkDegreeBy("test 4") - NumberedPolynomial { - o {} - o { 2 pow 1u } - o { 1 pow 2u; 3 pow 1u } - }.checkDegreeBy("test 5") - NumberedPolynomial { - o {} - o { 1 pow 1u; 2 pow 2u } - o { 2 pow 1u; 3 pow 2u } - o { 1 pow 2u; 3 pow 1u } - o { 4 pow 4u } - }.checkDegreeBy("test 6") + 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() { - val o = Rational(0) RationalField.numberedPolynomialSpace { assertEquals( 0, - NumberedPolynomial {}.countOfVariables, + NumberedPolynomial().countOfVariables, "test 1" ) assertEquals( 0, - NumberedPolynomial { - o {} - }.countOfVariables, + NumberedPolynomial( + listOf() to o + ).countOfVariables, "test 2" ) assertEquals( 3, - NumberedPolynomial { - o { 1 pow 1u; 2 pow 2u; 3 pow 3u } - }.countOfVariables, + NumberedPolynomial( + listOf(1u, 2u, 3u) to o + ).countOfVariables, "test 3" ) assertEquals( 3, - NumberedPolynomial { - o { 1 pow 0u; 2 pow 1u; 3 pow 2u; 4 pow 1u; 5 pow 0u } - }.countOfVariables, + NumberedPolynomial( + listOf(0u, 1u, 2u, 1u, 0u) to o + ).countOfVariables, "test 4" ) assertEquals( 3, - NumberedPolynomial { - o {} - o { 2 pow 1u } - o { 1 pow 2u; 3 pow 1u } - }.countOfVariables, + NumberedPolynomial( + listOf() to o, + listOf(0u, 1u) to o, + listOf(2u, 0u, 1u) to o, + ).countOfVariables, "test 5" ) assertEquals( 4, - NumberedPolynomial { - o {} - o { 1 pow 1u; 2 pow 2u } - o { 2 pow 1u; 3 pow 2u } - o { 1 pow 2u; 3 pow 1u } - o { 4 pow 4u } - }.countOfVariables, + 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() { - val o = Rational(0) RationalField.numberedRationalFunctionSpace { assertEquals( 0, NumberedRationalFunction( - NumberedPolynomial {} + NumberedPolynomial() ).countOfVariables, "test 1" ) assertEquals( 0, NumberedRationalFunction( - NumberedPolynomial {}, - NumberedPolynomial {} + NumberedPolynomial(), + NumberedPolynomial() ).countOfVariables, "test 2" ) assertEquals( 0, NumberedRationalFunction( - NumberedPolynomial { - o {} - } + NumberedPolynomial( + listOf() to o + ) ).countOfVariables, "test 3" ) assertEquals( 3, NumberedRationalFunction( - NumberedPolynomial { - o { 1 pow 1u; 2 pow 2u; 3 pow 3u } - } + NumberedPolynomial( + listOf(1u, 2u, 3u) to o + ) ).countOfVariables, "test 4" ) assertEquals( 3, NumberedRationalFunction( - NumberedPolynomial { - o { 2 pow 1u; 4 pow 1u } - }, - NumberedPolynomial { - o { 1 pow 0u; 3 pow 2u; 5 pow 0u } - } + NumberedPolynomial( + listOf(0u, 1u, 0u, 1u) to o + ), + NumberedPolynomial( + listOf(0u, 0u, 2u) to o + ) ).countOfVariables, "test 5" ) assertEquals( 3, NumberedRationalFunction( - NumberedPolynomial { - o {} - o { 2 pow 1u } - o { 1 pow 2u; 3 pow 1u } - } + NumberedPolynomial( + listOf() to o, + listOf(0u, 1u) to o, + listOf(2u, 0u, 1u) to o, + ) ).countOfVariables, "test 6" ) assertEquals( 4, NumberedRationalFunction( - NumberedPolynomial { - o {} - o { 1 pow 1u; 2 pow 2u } - o { 1 pow 2u; 3 pow 1u } - }, NumberedPolynomial { - o { 2 pow 1u; 3 pow 2u } - o { 4 pow 4u } - } + 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" ) -- 2.34.1 From 923c52737d4f5ca4e1153757b7079ebc2e19718b Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Wed, 6 Jul 2022 17:13:50 +0300 Subject: [PATCH 119/275] Adapt NumberedPolynomial tests to LabeledPolynomial tests. --- .../kmath/functions/LabeledPolynomial.kt | 42 +- .../kmath/functions/labeledConstructors.kt | 1 + .../functions/LabeledConstructorsTest.kt | 129 + .../kmath/functions/LabeledPolynomialTest.kt | 1872 ++++ .../functions/LabeledPolynomialUtilTest.kt | 8224 +++++++++++++++++ .../kmath/functions/NumberedPolynomialTest.kt | 18 +- .../kscience/kmath/test/misc/assertion.kt | 34 + 7 files changed, 10296 insertions(+), 24 deletions(-) create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt index 6d9af631a..1477796ea 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -177,14 +177,17 @@ public class LabeledPolynomialSpace>( * The operation is equivalent to sum of [other] copies of [this]. */ public override operator fun LabeledPolynomial.times(other: Int): LabeledPolynomial = - if (other == 0) zero - else LabeledPolynomial( - coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this[degs]!! * other - } - ) + when(other) { + 0 -> zero + 1 -> this + else -> LabeledPolynomial( + coefficients + .toMutableMap() + .apply { + for (degs in keys) this[degs] = this[degs]!! * other + } + ) + } /** * Returns sum of the integer represented as a polynomial and the polynomial. @@ -210,7 +213,7 @@ public class LabeledPolynomialSpace>( * The operation is equivalent to subtraction [this] copies of unit polynomial from [other]. */ public override operator fun Int.minus(other: LabeledPolynomial): LabeledPolynomial = - if (this == 0) other + if (this == 0) -other else with(other.coefficients) { if (isEmpty()) LabeledPolynomialAsIs(mapOf(emptyMap() to this@minus.asConstant())) else LabeledPolynomialAsIs( @@ -230,14 +233,17 @@ public class LabeledPolynomialSpace>( * The operation is equivalent to sum of [this] copies of [other]. */ public override operator fun Int.times(other: LabeledPolynomial): LabeledPolynomial = - if (this == 0) zero - else LabeledPolynomial( - other.coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this@times * this[degs]!! - } - ) + when(this) { + 0 -> zero + 1 -> other + else -> LabeledPolynomial( + other.coefficients + .toMutableMap() + .apply { + for (degs in keys) this[degs] = this@times * this[degs]!! + } + ) + } /** * Converts the integer [value] to polynomial. @@ -360,8 +366,6 @@ public class LabeledPolynomialSpace>( else LabeledPolynomialAsIs( toMutableMap() .apply { - forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } - val degs = emptyMap() this[degs] = getOrElse(degs) { constantZero } - other diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt index 8442d3f91..819a36449 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt @@ -302,6 +302,7 @@ public class DSL1LabeledPolynomialTermSignatureBuilder { * 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[this] = signature.getOrElse(this) { 0u } + deg } /** diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt new file mode 100644 index 000000000..edeaef6a7 --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt @@ -0,0 +1,129 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.expressions.symbol +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 { + val x by symbol + val y by symbol + val z by symbol + val t by symbol + + @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-functions/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt new file mode 100644 index 000000000..15c4c3656 --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt @@ -0,0 +1,1872 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.expressions.symbol +import space.kscience.kmath.test.misc.IntModuloRing +import space.kscience.kmath.test.misc.Rational +import space.kscience.kmath.test.misc.RationalField +import space.kscience.kmath.test.misc.m +import kotlin.test.* + + +// TODO: Тесты на конвертацию. +class LabeledPolynomialTest { + val x by symbol + val y by symbol + val z by symbol + val t by symbol + val s by symbol + val iota by symbol + + val o = Rational(0) + + @Test + @Ignore + fun test_Variable_Int_plus() { + // TODO + } + @Test + @Ignore + fun test_Variable_Int_minus() { + // TODO + } + @Test + @Ignore + fun test_Variable_Int_times() { + // TODO + } + @Test + @Ignore + fun test_Int_Variable_plus() { + // TODO + } + @Test + @Ignore + fun test_Int_Variable_minus() { + // TODO + } + @Test + @Ignore + fun test_Int_Variable_times() { + // TODO + } + @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 + @Ignore + fun test_Variable_Constant_plus() { + // TODO + } + @Test + @Ignore + fun test_Variable_Constant_minus() { + // TODO + } + @Test + @Ignore + fun test_Variable_Constant_times() { + // TODO + } + @Test + @Ignore + fun test_Constant_Variable_plus() { + // TODO + } + @Test + @Ignore + fun test_Constant_Variable_minus() { + // TODO + } + @Test + @Ignore + fun test_Constant_Variable_times() { + // TODO + } + @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 + @Ignore + fun test_Variable_unaryPlus(){ + // TODO + } + @Test + @Ignore + fun test_Variable_unaryMinus(){ + // TODO + } + @Test + @Ignore + fun test_Variable_Variable_plus(){ + // TODO + } + @Test + @Ignore + fun test_Variable_Variable_minus(){ + // TODO + } + @Test + @Ignore + fun test_Variable_Variable_times(){ + // TODO + } + @Test + @Ignore + fun test_Variable_Polynomial_plus(){ + // TODO + } + @Test + @Ignore + fun test_Variable_Polynomial_minus(){ + // TODO + } + @Test + @Ignore + fun test_Variable_Polynomial_times(){ + // TODO + } + @Test + @Ignore + fun test_Polynomial_Variable_plus(){ + // TODO + } + @Test + @Ignore + fun test_Polynomial_Variable_minus(){ + // TODO + } + @Test + @Ignore + fun test_Polynomial_Variable_times(){ + // TODO + } + @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-functions/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt new file mode 100644 index 000000000..cdfe309f9 --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt @@ -0,0 +1,8224 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.expressions.symbol +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.test.misc.Rational +import space.kscience.kmath.test.misc.RationalField +import space.kscience.kmath.test.misc.assertEquals +import kotlin.test.Ignore +import kotlin.test.Test +import kotlin.test.assertEquals + +class LabeledPolynomialUtilTest { + val x by symbol + val y by symbol + val iota by symbol + + @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-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt index f0a1128b4..007c3e5e9 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt @@ -7,14 +7,19 @@ package space.kscience.kmath.functions -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.test.misc.* -import kotlin.test.* +import space.kscience.kmath.test.misc.IntModuloRing +import space.kscience.kmath.test.misc.Rational +import space.kscience.kmath.test.misc.RationalField +import space.kscience.kmath.test.misc.m +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertSame +import kotlin.test.fail -@UnstableKMathAPI class NumberedPolynomialTest { - private val o = Rational(0) + val o = Rational(0) + @Test fun test_Polynomial_Int_plus() { RationalField.numberedPolynomialSpace { @@ -557,6 +562,7 @@ class NumberedPolynomialTest { ) assertEquals( NumberedPolynomial( + listOf() to Rational(0), listOf(3u) to Rational(-8, 9), listOf(0u, 4u) to Rational(-8, 7), ), @@ -650,6 +656,7 @@ class NumberedPolynomialTest { ) assertEquals( NumberedPolynomial( + listOf() to Rational(0), listOf(3u) to Rational(-8, 9), listOf(0u, 4u) to Rational(-8, 7), ), @@ -816,6 +823,7 @@ class NumberedPolynomialTest { ) assertEquals( NumberedPolynomial( + listOf() to Rational(0), listOf(3u) to Rational(-8, 9), listOf(0u, 4u) to Rational(-8, 7), ), diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/assertion.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/assertion.kt index 3ad482454..85180bd2a 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/assertion.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/assertion.kt @@ -5,6 +5,8 @@ package space.kscience.kmath.test.misc +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 @@ -28,6 +30,18 @@ fun assertEquals( 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, @@ -48,6 +62,26 @@ fun assertEquals( ) } +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, -- 2.34.1 From d3be07987c30e5dd786cdfb04cec4801d22b6d30 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Wed, 6 Jul 2022 23:16:25 +0300 Subject: [PATCH 120/275] Simplify usages of LabeledPolynomial constructing fabrics. Fix bugs. Add tests for variable's interoperability. --- .../kmath/functions/LabeledPolynomial.kt | 150 ++-- .../kmath/functions/ListPolynomial.kt | 5 - .../kmath/functions/NumberedPolynomial.kt | 5 - .../kscience/kmath/functions/Polynomial.kt | 2 +- .../kmath/functions/LabeledPolynomialTest.kt | 800 ++++++++++++++++-- 5 files changed, 816 insertions(+), 146 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt index 1477796ea..7f107a87f 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -77,63 +77,63 @@ public class LabeledPolynomialSpace>( * 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( + if (other == 0) LabeledPolynomialAsIs( mapOf(this@plus to 1U) to constantOne, - )) - else LabeledPolynomialAsIs(mapOf( + ) + else LabeledPolynomialAsIs( mapOf(this@plus to 1U) to constantOne, emptyMap() to constantOne * other, - )) + ) /** * 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( - mapOf(this@minus to 1U) to -constantOne, - )) - else LabeledPolynomialAsIs(mapOf( - mapOf(this@minus to 1U) to -constantOne, - emptyMap() to constantOne * other, - )) + if (other == 0) LabeledPolynomialAsIs( + mapOf(this@minus to 1U) to constantOne, + ) + else LabeledPolynomialAsIs( + mapOf(this@minus to 1U) to constantOne, + emptyMap() to constantOne * -other, + ) /** * 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( + else LabeledPolynomialAsIs( mapOf(this to 1U) to constantOne * other, - )) + ) /** * 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( + if (this == 0) LabeledPolynomialAsIs( mapOf(other to 1U) to constantOne, - )) - else LabeledPolynomialAsIs(mapOf( + ) + else LabeledPolynomialAsIs( mapOf(other to 1U) to constantOne, emptyMap() to constantOne * this@plus, - )) + ) /** * 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( + if (this == 0) LabeledPolynomialAsIs( mapOf(other to 1U) to -constantOne, - )) - else LabeledPolynomialAsIs(mapOf( + ) + 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( + else LabeledPolynomialAsIs( mapOf(other to 1U) to constantOne * this@times, - )) + ) /** * Returns sum of the polynomial and the integer represented as a polynomial. @@ -143,7 +143,7 @@ public class LabeledPolynomialSpace>( public override operator fun LabeledPolynomial.plus(other: Int): LabeledPolynomial = if (other == 0) this else with(coefficients) { - if (isEmpty()) LabeledPolynomialAsIs(mapOf(emptyMap() to other.asConstant())) + if (isEmpty()) other.asPolynomial() else LabeledPolynomialAsIs( toMutableMap() .apply { @@ -161,7 +161,7 @@ public class LabeledPolynomialSpace>( public override operator fun LabeledPolynomial.minus(other: Int): LabeledPolynomial = if (other == 0) this else with(coefficients) { - if (isEmpty()) LabeledPolynomialAsIs(mapOf(emptyMap() to (-other).asConstant())) + if (isEmpty()) (-other).asPolynomial() else LabeledPolynomialAsIs( toMutableMap() .apply { @@ -180,7 +180,7 @@ public class LabeledPolynomialSpace>( when(other) { 0 -> zero 1 -> this - else -> LabeledPolynomial( + else -> LabeledPolynomialAsIs( coefficients .toMutableMap() .apply { @@ -197,7 +197,7 @@ public class LabeledPolynomialSpace>( public override operator fun Int.plus(other: LabeledPolynomial): LabeledPolynomial = if (this == 0) other else with(other.coefficients) { - if (isEmpty()) LabeledPolynomialAsIs(mapOf(emptyMap() to this@plus.asConstant())) + if (isEmpty()) this@plus.asPolynomial() else LabeledPolynomialAsIs( toMutableMap() .apply { @@ -215,7 +215,7 @@ public class LabeledPolynomialSpace>( public override operator fun Int.minus(other: LabeledPolynomial): LabeledPolynomial = if (this == 0) -other else with(other.coefficients) { - if (isEmpty()) LabeledPolynomialAsIs(mapOf(emptyMap() to this@minus.asConstant())) + if (isEmpty()) this@minus.asPolynomial() else LabeledPolynomialAsIs( toMutableMap() .apply { @@ -236,7 +236,7 @@ public class LabeledPolynomialSpace>( when(this) { 0 -> zero 1 -> other - else -> LabeledPolynomial( + else -> LabeledPolynomialAsIs( other.coefficients .toMutableMap() .apply { @@ -245,65 +245,60 @@ public class LabeledPolynomialSpace>( ) } - /** - * Converts the integer [value] to polynomial. - */ - public override fun number(value: Int): LabeledPolynomial = number(constantNumber(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( + 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( - mapOf(this@minus to 1U) to -constantOne, - emptyMap() to other, - )) + 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( + 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( + 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( + 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( + 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 = with(other.coefficients) { - if (isEmpty()) LabeledPolynomialAsIs(mapOf(emptyMap() to this@plus)) + if (isEmpty()) this@plus.asLabeledPolynomial() else LabeledPolynomialAsIs( toMutableMap() .apply { @@ -318,7 +313,7 @@ public class LabeledPolynomialSpace>( */ override operator fun C.minus(other: LabeledPolynomial): LabeledPolynomial = with(other.coefficients) { - if (isEmpty()) LabeledPolynomialAsIs(mapOf(emptyMap() to this@minus)) + if (isEmpty()) this@minus.asLabeledPolynomial() else LabeledPolynomialAsIs( toMutableMap() .apply { @@ -347,7 +342,7 @@ public class LabeledPolynomialSpace>( */ override operator fun LabeledPolynomial.plus(other: C): LabeledPolynomial = with(coefficients) { - if (isEmpty()) LabeledPolynomialAsIs(mapOf(emptyMap() to other)) + if (isEmpty()) other.asLabeledPolynomial() else LabeledPolynomialAsIs( toMutableMap() .apply { @@ -362,7 +357,7 @@ public class LabeledPolynomialSpace>( */ override operator fun LabeledPolynomial.minus(other: C): LabeledPolynomial = with(coefficients) { - if (isEmpty()) LabeledPolynomialAsIs(mapOf(emptyMap() to other)) + if (isEmpty()) other.asLabeledPolynomial() else LabeledPolynomialAsIs( toMutableMap() .apply { @@ -387,60 +382,59 @@ public class LabeledPolynomialSpace>( /** * Converts the constant [value] to polynomial. */ - public override fun number(value: C): LabeledPolynomial = - LabeledPolynomial(mapOf(emptyMap() to value)) + 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( + 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( + 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( + if (this == other) LabeledPolynomialAsIs( mapOf(this to 1U) to constantOne * 2 - )) - else LabeledPolynomialAsIs(mapOf( + ) + 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( + 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( + if (this == other) LabeledPolynomialAsIs( mapOf(this to 2U) to constantOne - )) - else LabeledPolynomialAsIs(mapOf( + ) + 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 = with(other.coefficients) { - if (isEmpty()) LabeledPolynomialAsIs(mapOf(mapOf(this@plus to 1u) to constantOne)) + if (isEmpty()) this@plus.asPolynomial() else LabeledPolynomialAsIs( toMutableMap() .apply { @@ -455,15 +449,15 @@ public class LabeledPolynomialSpace>( */ public override operator fun Symbol.minus(other: LabeledPolynomial): LabeledPolynomial = with(other.coefficients) { - if (isEmpty()) LabeledPolynomialAsIs(mapOf(mapOf(this@minus to 1u) to constantOne)) + if (isEmpty()) this@minus.asPolynomial() else LabeledPolynomialAsIs( toMutableMap() .apply { - val degs = mapOf(this@minus to 1U) + val theVariableDegs = mapOf(this@minus to 1U) - forEach { (degs, c) -> if(degs != degs) this[degs] = -c } + forEach { (degs, c) -> if(degs != theVariableDegs) this[degs] = -c } - this[degs] = constantOne - getOrElse(degs) { constantZero } + this[theVariableDegs] = constantOne - getOrElse(theVariableDegs) { constantZero } } ) } @@ -481,7 +475,7 @@ public class LabeledPolynomialSpace>( */ public override operator fun LabeledPolynomial.plus(other: Symbol): LabeledPolynomial = with(coefficients) { - if (isEmpty()) LabeledPolynomialAsIs(mapOf(mapOf(other to 1u) to constantOne)) + if (isEmpty()) other.asPolynomial() else LabeledPolynomialAsIs( toMutableMap() .apply { @@ -496,13 +490,13 @@ public class LabeledPolynomialSpace>( */ public override operator fun LabeledPolynomial.minus(other: Symbol): LabeledPolynomial = with(coefficients) { - if (isEmpty()) LabeledPolynomialAsIs(mapOf(mapOf(other to 1u) to constantOne)) + if (isEmpty()) other.asPolynomial() else LabeledPolynomialAsIs( toMutableMap() .apply { val degs = mapOf(other to 1U) - this[degs] = constantOne - getOrElse(degs) { constantZero } + this[degs] = getOrElse(degs) { constantZero } - constantOne } ) } @@ -560,11 +554,11 @@ public class LabeledPolynomialSpace>( /** * Instance of zero polynomial (zero of the polynomial ring). */ - override val zero: LabeledPolynomial = LabeledPolynomialAsIs(mapOf(emptyMap() to constantZero)) + override val zero: LabeledPolynomial = LabeledPolynomialAsIs() /** * Instance of unit polynomial (unit of the polynomial ring). */ - override val one: LabeledPolynomial = LabeledPolynomialAsIs(mapOf(emptyMap() to constantOne)) + 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 diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt index a83b3915a..76e1a6bb6 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt @@ -172,11 +172,6 @@ public open class ListPolynomialSpace>( ) } - /** - * Converts the integer [value] to polynomial. - */ - public override fun number(value: Int): ListPolynomial = number(constantNumber(value)) - /** * Returns sum of the constant represented as a polynomial and the polynomial. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index ad421d7d3..f7dd9d8de 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -169,11 +169,6 @@ public class NumberedPolynomialSpace>( ) } - /** - * Converts the integer [value] to polynomial. - */ - public override fun number(value: Int): NumberedPolynomial = number(constantNumber(value)) - /** * Returns sum of the constant represented as a polynomial and the polynomial. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 12490d133..61ea5a342 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -112,7 +112,7 @@ public interface PolynomialSpace> : Ring

{ /** * Converts the integer [value] to polynomial. */ - public fun number(value: Int): P = one * value + public fun number(value: Int): P = number(constantNumber(value)) /** * Converts the integer to polynomial. */ diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt index 15c4c3656..95481f2ef 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.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("LocalVariableName") + package space.kscience.kmath.functions import space.kscience.kmath.expressions.Symbol @@ -26,34 +28,118 @@ class LabeledPolynomialTest { val o = Rational(0) @Test - @Ignore fun test_Variable_Int_plus() { - // TODO + 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 - @Ignore fun test_Variable_Int_minus() { - // TODO + 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 - @Ignore fun test_Variable_Int_times() { - // TODO + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(5), + ), + x * 5, + "test 1" + ) + assertSame( + zero, + x * 0, + "test 2" + ) + } } @Test - @Ignore fun test_Int_Variable_plus() { - // TODO + 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 - @Ignore fun test_Int_Variable_minus() { - // TODO + 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 - @Ignore fun test_Int_Variable_times() { - // TODO + 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() { @@ -516,34 +602,126 @@ class LabeledPolynomialTest { } } @Test - @Ignore fun test_Variable_Constant_plus() { - // TODO + 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 - @Ignore fun test_Variable_Constant_minus() { - // TODO + 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 - @Ignore fun test_Variable_Constant_times() { - // TODO + 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 - @Ignore fun test_Constant_Variable_plus() { - // TODO + 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 - @Ignore fun test_Constant_Variable_minus() { - // TODO + 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 - @Ignore fun test_Constant_Variable_times() { - // TODO + 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() { @@ -1068,59 +1246,567 @@ class LabeledPolynomialTest { } } @Test - @Ignore - fun test_Variable_unaryPlus(){ - // TODO + fun test_Variable_unaryPlus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(1), + ), + +x + ) + } } @Test - @Ignore - fun test_Variable_unaryMinus(){ - // TODO + fun test_Variable_unaryMinus() { + RationalField.labeledPolynomialSpace { + assertEquals( + LabeledPolynomialAsIs( + mapOf(x to 1u) to Rational(-1), + ), + -x + ) + } } @Test - @Ignore - fun test_Variable_Variable_plus(){ - // TODO + 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 - @Ignore - fun test_Variable_Variable_minus(){ - // TODO + 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 - @Ignore - fun test_Variable_Variable_times(){ - // TODO + 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 - @Ignore - fun test_Variable_Polynomial_plus(){ - // TODO + 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 - @Ignore - fun test_Variable_Polynomial_minus(){ - // TODO + 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 - @Ignore - fun test_Variable_Polynomial_times(){ - // TODO + 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 - @Ignore - fun test_Polynomial_Variable_plus(){ - // TODO + 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 - @Ignore - fun test_Polynomial_Variable_minus(){ - // TODO + 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 - @Ignore - fun test_Polynomial_Variable_times(){ - // TODO + 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() { -- 2.34.1 From d44a48bdb1c7d9fa1d8d0918373cf068d04a4c6a Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Mon, 11 Jul 2022 17:27:59 +0300 Subject: [PATCH 121/275] Moving to new modules. --- kmath-functions/build.gradle.kts | 13 +- .../kmath/functions/ListPolynomialTest.kt | 5 +- .../kmath/functions/ListPolynomialUtilTest.kt | 14 +- kmath-polynomialX/build.gradle.kts | 30 ++++ .../LabeledPolynomial.kt | 0 .../LabeledRationalFunction.kt | 0 .../NumberedPolynomial.kt | 0 .../NumberedRationalFunction.kt | 0 .../algebraicStub.kt | 146 ++++++++++++++++++ .../labeledConstructors.kt | 0 .../labeledUtil.kt | 0 .../numberedConstructors.kt | 0 .../numberedUtil.kt | 0 .../functions/LabeledConstructorsTest.kt | 10 +- .../kmath/functions/LabeledPolynomialTest.kt | 25 ++- .../functions/LabeledPolynomialUtilTest.kt | 14 +- .../functions/NumberedConstructorsTest.kt | 0 .../kmath/functions/NumberedPolynomialTest.kt | 11 +- .../functions/NumberedPolynomialUtilTest.kt | 13 +- settings.gradle.kts | 3 + test-utils-functions/build.gradle.kts | 14 ++ .../kmath/functions/testUtils}/IntModulo.kt | 55 +++---- .../functions/testUtils/IntModuloUtils.kt | 19 +++ .../kmath/functions/testUtils}/Rational.kt | 56 +++---- .../kmath/functions/testUtils/assertion.kt | 22 +++ .../kmath/functions/testUtils}/misc.kt | 8 +- test-utils-polynomialX/build.gradle.kts | 16 ++ .../kmath/functions/testUtils/BufferUtils.kt | 12 ++ .../kmath/functions/testUtils}/assertion.kt | 53 ++++--- .../kmath/functions/testUtils/misc.kt | 19 +++ 30 files changed, 419 insertions(+), 139 deletions(-) create mode 100644 kmath-polynomialX/build.gradle.kts rename {kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions => kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions}/LabeledPolynomial.kt (100%) rename {kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions => kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions}/LabeledRationalFunction.kt (100%) rename {kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions => kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions}/NumberedPolynomial.kt (100%) rename {kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions => kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions}/NumberedRationalFunction.kt (100%) create mode 100644 kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/algebraicStub.kt rename {kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions => kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions}/labeledConstructors.kt (100%) rename {kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions => kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions}/labeledUtil.kt (100%) rename {kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions => kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions}/numberedConstructors.kt (100%) rename {kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions => kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions}/numberedUtil.kt (100%) rename {kmath-functions => kmath-polynomialX}/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt (94%) rename {kmath-functions => kmath-polynomialX}/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt (99%) rename {kmath-functions => kmath-polynomialX}/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt (99%) rename {kmath-functions => kmath-polynomialX}/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt (100%) rename {kmath-functions => kmath-polynomialX}/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt (99%) rename {kmath-functions => kmath-polynomialX}/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt (99%) create mode 100644 test-utils-functions/build.gradle.kts rename {kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc => test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils}/IntModulo.kt (70%) create mode 100644 test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt rename {kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc => test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils}/Rational.kt (77%) create mode 100644 test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt rename {kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc => test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils}/misc.kt (76%) create mode 100644 test-utils-polynomialX/build.gradle.kts create mode 100644 test-utils-polynomialX/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/BufferUtils.kt rename {kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc => test-utils-polynomialX/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils}/assertion.kt (72%) create mode 100644 test-utils-polynomialX/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/misc.kt diff --git a/kmath-functions/build.gradle.kts b/kmath-functions/build.gradle.kts index fadbac091..0a8e8a1be 100644 --- a/kmath-functions/build.gradle.kts +++ b/kmath-functions/build.gradle.kts @@ -6,9 +6,16 @@ plugins { description = "Functions, integration and interpolation" -kotlin.sourceSets.commonMain { - dependencies { - api(project(":kmath-core")) +kotlin.sourceSets { + commonMain { + dependencies { + api(project(":kmath-core")) + } + } + commonTest { + dependencies { + api(projects.testUtilsFunctions) + } } } diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt index c4a7cc564..e7d8dfd8c 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt @@ -7,7 +7,10 @@ package space.kscience.kmath.functions -import space.kscience.kmath.test.misc.* +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.* diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt index 685a2a506..339643d02 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt @@ -6,9 +6,9 @@ package space.kscience.kmath.functions import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.test.misc.Rational -import space.kscience.kmath.test.misc.RationalField -import space.kscience.kmath.test.misc.assertFailsWithTypeAndMessage +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 @@ -64,7 +64,7 @@ class ListPolynomialUtilTest { ) assertEquals( Rational(25057, 21000), - ListPolynomial(Rational(5,8), Rational(8, 3), Rational(4, 7), Rational(3, 2)) + ListPolynomial(Rational(5, 8), Rational(8, 3), Rational(4, 7), Rational(3, 2)) .substitute(RationalField, Rational(1, 5)), "test 2" ) @@ -76,13 +76,13 @@ class ListPolynomialUtilTest { ) assertEquals( Rational(4961, 4200), - ListPolynomial(Rational(5,8), Rational(8, 3), Rational(4, 7), Rational(0)) + 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)) + ListPolynomial(Rational(5, 8), Rational(8, 3), Rational(0), Rational(3, 2)) .substitute(RationalField, Rational(1, 5)), "test 5" ) @@ -233,7 +233,7 @@ class ListPolynomialUtilTest { ListPolynomial( Rational(-13, 9), Rational(5, 3), - Rational(-5, 4) , + Rational(-5, 4), Rational(0), Rational(0), Rational(0), diff --git a/kmath-polynomialX/build.gradle.kts b/kmath-polynomialX/build.gradle.kts new file mode 100644 index 000000000..51b3c0665 --- /dev/null +++ b/kmath-polynomialX/build.gradle.kts @@ -0,0 +1,30 @@ +plugins { + kotlin("multiplatform") + id("ru.mipt.npm.gradle.common") + id("ru.mipt.npm.gradle.native") +} + +description = "Polynomial extra utilities and rational functions" + +kotlin.sourceSets { + commonMain { + dependencies { + api(projects.kmathCore) + api(projects.kmathFunctions) + } + } + commonTest { + dependencies { + api(projects.testUtilsFunctions) + api(projects.testUtilsPolynomialX) + api(kotlin("test")) + } + } +} + +readme { + maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) + +// feature("TODO") { "TODO" } +} diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/LabeledPolynomial.kt similarity index 100% rename from kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt rename to kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/LabeledPolynomial.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/LabeledRationalFunction.kt similarity index 100% rename from kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt rename to kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/LabeledRationalFunction.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/NumberedPolynomial.kt similarity index 100% rename from kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt rename to kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/NumberedPolynomial.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/NumberedRationalFunction.kt similarity index 100% rename from kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt rename to kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/NumberedRationalFunction.kt diff --git a/kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/algebraicStub.kt b/kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/algebraicStub.kt new file mode 100644 index 000000000..b40aa4775 --- /dev/null +++ b/kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/algebraicStub.kt @@ -0,0 +1,146 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.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-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt b/kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/labeledConstructors.kt similarity index 100% rename from kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt rename to kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/labeledConstructors.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt b/kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/labeledUtil.kt similarity index 100% rename from kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt rename to kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/labeledUtil.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt b/kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/numberedConstructors.kt similarity index 100% rename from kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt rename to kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/numberedConstructors.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt b/kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/numberedUtil.kt similarity index 100% rename from kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt rename to kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/numberedUtil.kt diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt b/kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt similarity index 94% rename from kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt rename to kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt index edeaef6a7..081cf06e4 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt +++ b/kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt @@ -6,19 +6,17 @@ package space.kscience.kmath.functions import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.expressions.symbol import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.algebra import space.kscience.kmath.operations.invoke +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.Test import kotlin.test.assertEquals class LabeledConstructorsTest { - val x by symbol - val y by symbol - val z by symbol - val t by symbol - @Test @UnstableKMathAPI fun testDSL1() { diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt b/kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt similarity index 99% rename from kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt rename to kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt index 95481f2ef..d2d417a02 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt +++ b/kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt @@ -8,25 +8,22 @@ package space.kscience.kmath.functions import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.expressions.symbol -import space.kscience.kmath.test.misc.IntModuloRing -import space.kscience.kmath.test.misc.Rational -import space.kscience.kmath.test.misc.RationalField -import space.kscience.kmath.test.misc.m +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.o +import space.kscience.kmath.functions.testUtils.m import kotlin.test.* +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.functions.testUtils.t +import space.kscience.kmath.functions.testUtils.s +import space.kscience.kmath.functions.testUtils.iota // TODO: Тесты на конвертацию. class LabeledPolynomialTest { - val x by symbol - val y by symbol - val z by symbol - val t by symbol - val s by symbol - val iota by symbol - - val o = Rational(0) - @Test fun test_Variable_Int_plus() { RationalField.labeledPolynomialSpace { diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt b/kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt similarity index 99% rename from kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt rename to kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt index cdfe309f9..37329a318 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt +++ b/kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt @@ -6,20 +6,18 @@ package space.kscience.kmath.functions import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.expressions.symbol import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.test.misc.Rational -import space.kscience.kmath.test.misc.RationalField -import space.kscience.kmath.test.misc.assertEquals +import space.kscience.kmath.functions.testUtils.Rational +import space.kscience.kmath.functions.testUtils.RationalField import kotlin.test.Ignore import kotlin.test.Test import kotlin.test.assertEquals +import space.kscience.kmath.functions.testUtils.x +import space.kscience.kmath.functions.testUtils.y +import space.kscience.kmath.functions.testUtils.iota +import space.kscience.kmath.functions.testUtils.assertEquals class LabeledPolynomialUtilTest { - val x by symbol - val y by symbol - val iota by symbol - @Test fun test_Polynomial_substitute_Double() { assertEquals( diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt b/kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt similarity index 100% rename from kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt rename to kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt b/kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt similarity index 99% rename from kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt rename to kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt index 007c3e5e9..ec2e34520 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt +++ b/kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt @@ -7,10 +7,11 @@ package space.kscience.kmath.functions -import space.kscience.kmath.test.misc.IntModuloRing -import space.kscience.kmath.test.misc.Rational -import space.kscience.kmath.test.misc.RationalField -import space.kscience.kmath.test.misc.m +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 @@ -18,8 +19,6 @@ import kotlin.test.fail class NumberedPolynomialTest { - val o = Rational(0) - @Test fun test_Polynomial_Int_plus() { RationalField.numberedPolynomialSpace { diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt b/kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt similarity index 99% rename from kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt rename to kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt index 1b87d3fcf..82f1e561a 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt +++ b/kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt @@ -6,19 +6,16 @@ package space.kscience.kmath.functions import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.asBuffer -import space.kscience.kmath.test.misc.Rational -import space.kscience.kmath.test.misc.RationalField -import space.kscience.kmath.test.misc.assertEquals -import space.kscience.kmath.test.misc.assertFailsWithTypeAndMessage +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 -fun bufferOf(vararg elements: T): Buffer = elements.asBuffer() - class NumberedPolynomialUtilTest { @Test fun test_Polynomial_substitute_Double_Map() { diff --git a/settings.gradle.kts b/settings.gradle.kts index e3c621e9a..543d08001 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -26,6 +26,9 @@ include( ":kmath-core", ":kmath-coroutines", ":kmath-functions", + ":test-utils-functions", + ":kmath-polynomialX", + ":test-utils-polynomialX", ":kmath-histograms", ":kmath-commons", ":kmath-viktor", diff --git a/test-utils-functions/build.gradle.kts b/test-utils-functions/build.gradle.kts new file mode 100644 index 000000000..8476abecc --- /dev/null +++ b/test-utils-functions/build.gradle.kts @@ -0,0 +1,14 @@ +plugins { + id("ru.mipt.npm.gradle.mpp") + id("ru.mipt.npm.gradle.native") +} + +kotlin.sourceSets { + commonMain { + dependencies { + api(projects.kmathCore) + api(projects.kmathFunctions) + api(kotlin("test")) + } + } +} diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt b/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt similarity index 70% rename from kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt rename to test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt index f6e8457bb..933c4dc4c 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/IntModulo.kt +++ b/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt @@ -5,40 +5,37 @@ @file:Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress") -package space.kscience.kmath.test.misc +package space.kscience.kmath.functions.testUtils -import space.kscience.kmath.functions.ListPolynomial -import space.kscience.kmath.functions.ListPolynomialSpace -import space.kscience.kmath.functions.PolynomialSpaceOverRing import space.kscience.kmath.operations.Ring -class IntModulo { - val residue: Int - val modulus: Int +public class IntModulo { + public val residue: Int + public 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(modulus) + this.residue = residue.mod(this.modulus) } else { this.residue = residue this.modulus = modulus } } - constructor(residue: Int, modulus: Int) : this(residue, modulus, true) + public constructor(residue: Int, modulus: Int) : this(residue, modulus, true) - operator fun unaryPlus(): IntModulo = this - operator fun unaryMinus(): IntModulo = + public operator fun unaryPlus(): IntModulo = this + public operator fun unaryMinus(): IntModulo = IntModulo( if (residue == 0) 0 else modulus - residue, modulus, toCheckInput = false ) - operator fun plus(other: IntModulo): IntModulo { + public operator fun plus(other: IntModulo): IntModulo { require(modulus == other.modulus) { "can not add two residue different modulo" } return IntModulo( (residue + other.residue) % modulus, @@ -46,13 +43,13 @@ class IntModulo { toCheckInput = false ) } - operator fun plus(other: Int): IntModulo = + public operator fun plus(other: Int): IntModulo = IntModulo( (residue + other) % modulus, modulus, toCheckInput = false ) - operator fun minus(other: IntModulo): IntModulo { + public operator fun minus(other: IntModulo): IntModulo { require(modulus == other.modulus) { "can not subtract two residue different modulo" } return IntModulo( (residue - other.residue) % modulus, @@ -60,13 +57,13 @@ class IntModulo { toCheckInput = false ) } - operator fun minus(other: Int): IntModulo = + public operator fun minus(other: Int): IntModulo = IntModulo( (residue - other) % modulus, modulus, toCheckInput = false ) - operator fun times(other: IntModulo): IntModulo { + public operator fun times(other: IntModulo): IntModulo { require(modulus == other.modulus) { "can not multiply two residue different modulo" } return IntModulo( (residue * other.residue) % modulus, @@ -74,13 +71,13 @@ class IntModulo { toCheckInput = false ) } - operator fun times(other: Int): IntModulo = + public operator fun times(other: Int): IntModulo = IntModulo( (residue * other) % modulus, modulus, toCheckInput = false ) - operator fun div(other: IntModulo): IntModulo { + public 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" } @@ -90,7 +87,7 @@ class IntModulo { toCheckInput = false ) } - operator fun div(other: Int): IntModulo { + public 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( @@ -111,11 +108,11 @@ class IntModulo { } @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE") -class IntModuloRing : Ring { +public class IntModuloRing : Ring { - val modulus: Int + public val modulus: Int - constructor(modulus: Int) { + public constructor(modulus: Int) { require(modulus != 0) { "modulus can not be zero" } this.modulus = if (modulus < 0) -modulus else modulus } @@ -123,7 +120,7 @@ class IntModuloRing : Ring { 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(arg, modulus, toCheckInput = false) + public 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 @@ -132,13 +129,5 @@ class IntModuloRing : Ring { 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 -} - -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(arg, modulus) -fun PolynomialSpaceOverRing.m(arg: Int) = IntModulo(arg, ring.modulus) \ No newline at end of file + public inline fun IntModulo.div(arg: IntModulo): IntModulo = this / arg +} \ No newline at end of file diff --git a/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt b/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt new file mode 100644 index 000000000..4b65fbea1 --- /dev/null +++ b/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions.testUtils + +import space.kscience.kmath.functions.ListPolynomial +import space.kscience.kmath.functions.ListPolynomialSpace +import space.kscience.kmath.functions.PolynomialSpaceOverRing + + +public fun ListPolynomialSpace.ListPolynomial(vararg coefs: Int): ListPolynomial = + ListPolynomial(coefs.map { IntModulo(it, ring.modulus) }) +public fun IntModuloRing.ListPolynomial(vararg coefs: Int): ListPolynomial = + ListPolynomial(coefs.map { IntModulo(it, modulus) }) + +public fun IntModuloRing.m(arg: Int): IntModulo = IntModulo(arg, modulus) +public fun PolynomialSpaceOverRing.m(arg: Int): IntModulo = IntModulo(arg, ring.modulus) \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt b/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt similarity index 77% rename from kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt rename to test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt index 731621658..27b0eb21e 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/Rational.kt +++ b/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt @@ -5,21 +5,21 @@ @file:Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress") -package space.kscience.kmath.test.misc +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) +public class Rational { + public companion object { + public val ZERO: Rational = Rational(0L) + public val ONE: Rational = Rational(1L) } - val numerator: Long - val denominator: Long + public val numerator: Long + public val denominator: Long internal constructor(numerator: Long, denominator: Long, toCheckInput: Boolean = true) { if (toCheckInput) { @@ -35,16 +35,16 @@ class Rational { } } - 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) + public constructor(numerator: Int, denominator: Int) : this(numerator.toLong(), denominator.toLong(), true) + public constructor(numerator: Int, denominator: Long) : this(numerator.toLong(), denominator, true) + public constructor(numerator: Long, denominator: Int) : this(numerator, denominator.toLong(), true) + public constructor(numerator: Long, denominator: Long) : this(numerator, denominator, true) + public constructor(numerator: Int) : this(numerator.toLong(), 1L, false) + public 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 { + public operator fun unaryPlus(): Rational = this + public operator fun unaryMinus(): Rational = Rational(-this.numerator, this.denominator) + public operator fun plus(other: Rational): Rational { val denominatorsGcd = gcd(denominator, other.denominator) val dividedThisDenominator = denominator / denominatorsGcd val dividedOtherDenominator = other.denominator / denominatorsGcd @@ -56,19 +56,19 @@ class Rational { toCheckInput = false ) } - operator fun plus(other: Int): Rational = + public operator fun plus(other: Int): Rational = Rational( numerator + denominator * other.toLong(), denominator, toCheckInput = false ) - operator fun plus(other: Long): Rational = + public operator fun plus(other: Long): Rational = Rational( numerator + denominator * other, denominator, toCheckInput = false ) - operator fun minus(other: Rational): Rational { + public operator fun minus(other: Rational): Rational { val denominatorsGcd = gcd(denominator, other.denominator) val dividedThisDenominator = denominator / denominatorsGcd val dividedOtherDenominator = other.denominator / denominatorsGcd @@ -80,19 +80,19 @@ class Rational { toCheckInput = false ) } - operator fun minus(other: Int): Rational = + public operator fun minus(other: Int): Rational = Rational( numerator - denominator * other.toLong(), denominator, toCheckInput = false ) - operator fun minus(other: Long): Rational = + public operator fun minus(other: Long): Rational = Rational( numerator - denominator * other, denominator, toCheckInput = false ) - operator fun times(other: Rational): Rational { + public operator fun times(other: Rational): Rational { val thisDenominatorAndOtherNumeratorGcd = gcd(denominator, other.numerator) val otherDenominatorAndThisNumeratorGcd = gcd(other.denominator, numerator) return Rational( @@ -101,7 +101,7 @@ class Rational { toCheckInput = false ) } - operator fun times(other: Int): Rational { + public operator fun times(other: Int): Rational { val other = other.toLong() val denominatorAndOtherGcd = gcd(denominator, other) return Rational( @@ -110,7 +110,7 @@ class Rational { toCheckInput = false ) } - operator fun times(other: Long): Rational { + public operator fun times(other: Long): Rational { val denominatorAndOtherGcd = gcd(denominator, other) return Rational( numerator * (other / denominatorAndOtherGcd), @@ -118,7 +118,7 @@ class Rational { toCheckInput = false ) } - operator fun div(other: Rational): Rational { + public operator fun div(other: Rational): Rational { val denominatorsGcd = gcd(denominator, other.denominator) val numeratorsGcd = gcd(numerator, other.numerator) return Rational( @@ -126,7 +126,7 @@ class Rational { (denominator / denominatorsGcd) * (other.numerator / numeratorsGcd) ) } - operator fun div(other: Int): Rational { + public operator fun div(other: Int): Rational { val other = other.toLong() val numeratorAndOtherGcd = gcd(numerator, other) return Rational( @@ -135,7 +135,7 @@ class Rational { toCheckInput = false ) } - operator fun div(other: Long): Rational { + public operator fun div(other: Long): Rational { val numeratorAndOtherGcd = gcd(numerator, other) return Rational( numerator / numeratorAndOtherGcd, @@ -158,7 +158,7 @@ class Rational { @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE") @OptIn(UnstableKMathAPI::class) -object RationalField : Field, NumbersAddOps { +public object RationalField : Field, NumbersAddOps { override inline val zero: Rational get() = Rational.ZERO override inline val one: Rational get() = Rational.ONE diff --git a/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt b/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt new file mode 100644 index 000000000..5cf82996f --- /dev/null +++ b/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions.testUtils + +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith + + +public 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-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt b/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/misc.kt similarity index 76% rename from kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt rename to test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/misc.kt index ed41b9245..ff67f19d8 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/misc.kt +++ b/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/misc.kt @@ -3,16 +3,16 @@ * 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.test.misc +package space.kscience.kmath.functions.testUtils import kotlin.math.abs -data class BezoutIdentityWithGCD(val first: T, val second: T, val gcd: T) +internal data class BezoutIdentityWithGCD(val first: T, val second: T, val gcd: T) -tailrec fun gcd(a: Long, b: Long): Long = if (a == 0L) abs(b) else gcd(b % a, a) +internal tailrec fun gcd(a: Long, b: Long): Long = if (a == 0L) abs(b) else gcd(b % a, a) -fun bezoutIdentityWithGCD(a: Int, b: Int): BezoutIdentityWithGCD = +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) } diff --git a/test-utils-polynomialX/build.gradle.kts b/test-utils-polynomialX/build.gradle.kts new file mode 100644 index 000000000..f20e1b8bb --- /dev/null +++ b/test-utils-polynomialX/build.gradle.kts @@ -0,0 +1,16 @@ +plugins { + id("ru.mipt.npm.gradle.mpp") + id("ru.mipt.npm.gradle.native") +} + +kotlin.sourceSets { + commonMain { + dependencies { + api(projects.kmathCore) + api(projects.kmathFunctions) + api(projects.testUtilsFunctions) + api(projects.kmathPolynomialX) + api(kotlin("test")) + } + } +} diff --git a/test-utils-polynomialX/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/BufferUtils.kt b/test-utils-polynomialX/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/BufferUtils.kt new file mode 100644 index 000000000..afd26dd36 --- /dev/null +++ b/test-utils-polynomialX/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/BufferUtils.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions.testUtils + +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.asBuffer + + +public fun bufferOf(vararg elements: T): Buffer = elements.asBuffer() \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/assertion.kt b/test-utils-polynomialX/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt similarity index 72% rename from kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/assertion.kt rename to test-utils-polynomialX/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt index 85180bd2a..9ca5f43a3 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/test/misc/assertion.kt +++ b/test-utils-polynomialX/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt @@ -3,7 +3,7 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -package space.kscience.kmath.test.misc +package space.kscience.kmath.functions.testUtils import space.kscience.kmath.functions.LabeledPolynomial import space.kscience.kmath.functions.LabeledRationalFunction @@ -13,36 +13,45 @@ import kotlin.test.assertEquals import kotlin.test.assertFailsWith -fun assertContentEquals(expected: Map, actual: Map, absoluteTolerance: Double, message: String? = null) { +public 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( +public fun assertEquals( expected: NumberedPolynomial, actual: NumberedPolynomial, absoluteTolerance: Double, message: String? = null -) = assertContentEquals( - expected.coefficients, - actual.coefficients, - absoluteTolerance, - message -) +) { + assertContentEquals( + expected.coefficients, + actual.coefficients, + absoluteTolerance, + message + ) +} -fun assertEquals( +public fun assertEquals( expected: LabeledPolynomial, actual: LabeledPolynomial, absoluteTolerance: Double, message: String? = null -) = assertContentEquals( - expected.coefficients, - actual.coefficients, - absoluteTolerance, - message -) +) { + assertContentEquals( + expected.coefficients, + actual.coefficients, + absoluteTolerance, + message + ) +} -fun assertEquals( +public fun assertEquals( expected: NumberedRationalFunction, actual: NumberedRationalFunction, absoluteTolerance: Double, @@ -62,7 +71,7 @@ fun assertEquals( ) } -fun assertEquals( +public fun assertEquals( expected: LabeledRationalFunction, actual: LabeledRationalFunction, absoluteTolerance: Double, @@ -82,13 +91,15 @@ fun assertEquals( ) } -inline fun assertFailsWithTypeAndMessage( +// FIXME: Don't understand why but the same function from test-utils-functions module can not be used +public 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 + ) +} \ No newline at end of file diff --git a/test-utils-polynomialX/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/misc.kt b/test-utils-polynomialX/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/misc.kt new file mode 100644 index 000000000..051fc0f37 --- /dev/null +++ b/test-utils-polynomialX/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/misc.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions.testUtils + +import space.kscience.kmath.expressions.Symbol +import space.kscience.kmath.expressions.symbol + + +public val o: Rational = Rational(0) + +public val x: Symbol by symbol +public val y: Symbol by symbol +public val z: Symbol by symbol +public val t: Symbol by symbol +public val s: Symbol by symbol +public val iota: Symbol by symbol \ No newline at end of file -- 2.34.1 From 1c719b9e709ec07920545a99db6c7c9f274b8908 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Mon, 11 Jul 2022 17:52:46 +0300 Subject: [PATCH 122/275] Fix examples. --- examples/build.gradle.kts | 2 ++ .../main/kotlin/space/kscience/kmath/functions/polynomials.kt | 2 ++ 2 files changed, 4 insertions(+) diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 60f8f5aed..67b28cd85 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -15,6 +15,8 @@ dependencies { implementation(project(":kmath-coroutines")) implementation(project(":kmath-commons")) implementation(project(":kmath-complex")) + implementation(project(":kmath-functions")) + implementation(project(":kmath-polynomialX")) 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 index 7843a0210..4151b0283 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.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("LocalVariableName") + package space.kscience.kmath.functions import space.kscience.kmath.expressions.Symbol -- 2.34.1 From 51dd72e48f2043a00bc2a5da75dbf8b6c1c2039b Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Mon, 11 Jul 2022 22:39:13 +0300 Subject: [PATCH 123/275] Finish move. --- examples/build.gradle.kts | 2 +- .../build.gradle.kts | 4 +- .../LabeledPolynomial.kt | 0 .../LabeledRationalFunction.kt | 0 .../ListPolynomial.kt | 387 ++++++++++++++ .../ListRationalFunction.kt | 0 .../NumberedPolynomial.kt | 0 .../NumberedRationalFunction.kt | 0 .../Polynomial.kt | 502 ++++++++++++++++++ .../RationalFunction.kt | 3 +- .../algebraicStub.kt | 0 .../labeledConstructors.kt | 0 .../labeledUtil.kt | 2 +- .../listConstructors.kt | 92 ++++ .../listUtil.kt | 255 +++++++++ .../space.kscience.kmath.functions/misc.kt | 22 + .../numberedConstructors.kt | 0 .../numberedUtil.kt | 0 .../functions/LabeledConstructorsTest.kt | 6 +- .../kmath/functions/LabeledPolynomialTest.kt | 10 +- .../functions/LabeledPolynomialUtilTest.kt | 9 +- .../functions/NumberedConstructorsTest.kt | 0 .../kmath/functions/NumberedPolynomialTest.kt | 0 .../functions/NumberedPolynomialUtilTest.kt | 0 settings.gradle.kts | 4 +- .../build.gradle.kts | 4 +- .../kmath/functions/testUtils/BufferUtils.kt | 0 .../kmath/functions/testUtils/assertion.kt | 0 .../kmath/functions/testUtils/misc.kt | 0 29 files changed, 1278 insertions(+), 24 deletions(-) rename {kmath-polynomialX => kmath-polynomial}/build.gradle.kts (81%) rename {kmath-polynomialX => kmath-polynomial}/src/commonMain/kotlin/space.kscience.kmath.functions/LabeledPolynomial.kt (100%) rename {kmath-polynomialX => kmath-polynomial}/src/commonMain/kotlin/space.kscience.kmath.functions/LabeledRationalFunction.kt (100%) create mode 100644 kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/ListPolynomial.kt rename {kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions => kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions}/ListRationalFunction.kt (100%) rename {kmath-polynomialX => kmath-polynomial}/src/commonMain/kotlin/space.kscience.kmath.functions/NumberedPolynomial.kt (100%) rename {kmath-polynomialX => kmath-polynomial}/src/commonMain/kotlin/space.kscience.kmath.functions/NumberedRationalFunction.kt (100%) create mode 100644 kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/Polynomial.kt rename {kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions => kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions}/RationalFunction.kt (99%) rename {kmath-polynomialX => kmath-polynomial}/src/commonMain/kotlin/space.kscience.kmath.functions/algebraicStub.kt (100%) rename {kmath-polynomialX => kmath-polynomial}/src/commonMain/kotlin/space.kscience.kmath.functions/labeledConstructors.kt (100%) rename {kmath-polynomialX => kmath-polynomial}/src/commonMain/kotlin/space.kscience.kmath.functions/labeledUtil.kt (99%) create mode 100644 kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/listConstructors.kt create mode 100644 kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/listUtil.kt create mode 100644 kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/misc.kt rename {kmath-polynomialX => kmath-polynomial}/src/commonMain/kotlin/space.kscience.kmath.functions/numberedConstructors.kt (100%) rename {kmath-polynomialX => kmath-polynomial}/src/commonMain/kotlin/space.kscience.kmath.functions/numberedUtil.kt (100%) rename {kmath-polynomialX => kmath-polynomial}/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt (99%) rename {kmath-polynomialX => kmath-polynomial}/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt (99%) rename {kmath-polynomialX => kmath-polynomial}/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt (99%) rename {kmath-polynomialX => kmath-polynomial}/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt (100%) rename {kmath-polynomialX => kmath-polynomial}/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt (100%) rename {kmath-polynomialX => kmath-polynomial}/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt (100%) rename {test-utils-polynomialX => test-utils-polynomial}/build.gradle.kts (63%) rename {test-utils-polynomialX => test-utils-polynomial}/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/BufferUtils.kt (100%) rename {test-utils-polynomialX => test-utils-polynomial}/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt (100%) rename {test-utils-polynomialX => test-utils-polynomial}/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/misc.kt (100%) diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 67b28cd85..aa5c1f47a 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -16,7 +16,7 @@ dependencies { implementation(project(":kmath-commons")) implementation(project(":kmath-complex")) implementation(project(":kmath-functions")) - implementation(project(":kmath-polynomialX")) + implementation(project(":kmath-polynomial")) implementation(project(":kmath-optimization")) implementation(project(":kmath-stat")) implementation(project(":kmath-viktor")) diff --git a/kmath-polynomialX/build.gradle.kts b/kmath-polynomial/build.gradle.kts similarity index 81% rename from kmath-polynomialX/build.gradle.kts rename to kmath-polynomial/build.gradle.kts index 51b3c0665..dcfcb1b46 100644 --- a/kmath-polynomialX/build.gradle.kts +++ b/kmath-polynomial/build.gradle.kts @@ -10,13 +10,11 @@ kotlin.sourceSets { commonMain { dependencies { api(projects.kmathCore) - api(projects.kmathFunctions) } } commonTest { dependencies { - api(projects.testUtilsFunctions) - api(projects.testUtilsPolynomialX) + api(projects.testUtilsPolynomial) api(kotlin("test")) } } diff --git a/kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/LabeledPolynomial.kt b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/LabeledPolynomial.kt similarity index 100% rename from kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/LabeledPolynomial.kt rename to kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/LabeledPolynomial.kt diff --git a/kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/LabeledRationalFunction.kt b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/LabeledRationalFunction.kt similarity index 100% rename from kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/LabeledRationalFunction.kt rename to kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/LabeledRationalFunction.kt diff --git a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/ListPolynomial.kt b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/ListPolynomial.kt new file mode 100644 index 000000000..76e1a6bb6 --- /dev/null +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/ListPolynomial.kt @@ -0,0 +1,387 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +@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. + */ + public val coefficients: List +) : Polynomial { + 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 + .toMutableList() + .apply { + for (deg in indices) this[deg] = this[deg] * 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 + .toMutableList() + .apply { + for (deg in indices) this[deg] = this@times * this[deg] + } + ) + } + + /** + * Returns sum of the constant represented as a polynomial and the polynomial. + */ + public 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 + .toMutableList() + .apply { + for (deg in indices) this[deg] = this@times * this[deg] + } + ) + + /** + * Returns sum of the constant represented as a polynomial and the polynomial. + */ + public 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 + .toMutableList() + .apply { + for (deg in indices) this[deg] = this[deg] * 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-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/ListRationalFunction.kt similarity index 100% rename from kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt rename to kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/ListRationalFunction.kt diff --git a/kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/NumberedPolynomial.kt b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/NumberedPolynomial.kt similarity index 100% rename from kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/NumberedPolynomial.kt rename to kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/NumberedPolynomial.kt diff --git a/kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/NumberedRationalFunction.kt b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/NumberedRationalFunction.kt similarity index 100% rename from kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/NumberedRationalFunction.kt rename to kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/NumberedRationalFunction.kt diff --git a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/Polynomial.kt b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/Polynomial.kt new file mode 100644 index 000000000..61ea5a342 --- /dev/null +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/Polynomial.kt @@ -0,0 +1,502 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.invoke +import kotlin.js.JsName +import kotlin.jvm.JvmName + + +/** + * Abstraction of polynomials. + */ +public interface Polynomial + +/** + * 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]. + */ + 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]. + */ + 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]. + */ + 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]. + */ + 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]. + */ + 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]. + */ + 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. + */ + public operator fun C.plus(other: P): P + /** + * Returns difference between the constant represented as a polynomial and the polynomial. + */ + public operator fun C.minus(other: P): P + /** + * Returns product of the constant represented as a polynomial and the polynomial. + */ + public operator fun C.times(other: P): P + + /** + * Returns sum of the constant represented as a polynomial and the polynomial. + */ + public operator fun P.plus(other: C): P + /** + * Returns difference between the constant represented as a polynomial and the polynomial. + */ + public operator fun P.minus(other: C): P + /** + * Returns product of the constant represented as a polynomial and the polynomial. + */ + 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, A: Ring> : 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]. + */ + 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]. + */ + 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]. + */ + 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]. + */ + 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]. + */ + 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]. + */ + 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") + 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") + 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") + 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") + 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") + 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") + 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") + 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") + 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") + 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") + 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") + 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") + 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-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/RationalFunction.kt similarity index 99% rename from kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt rename to kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/RationalFunction.kt index 1782dba74..f664ae9db 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/RationalFunction.kt @@ -5,7 +5,8 @@ package space.kscience.kmath.functions -import space.kscience.kmath.operations.* +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.invoke import kotlin.js.JsName import kotlin.jvm.JvmName diff --git a/kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/algebraicStub.kt b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/algebraicStub.kt similarity index 100% rename from kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/algebraicStub.kt rename to kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/algebraicStub.kt diff --git a/kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/labeledConstructors.kt b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/labeledConstructors.kt similarity index 100% rename from kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/labeledConstructors.kt rename to kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/labeledConstructors.kt diff --git a/kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/labeledUtil.kt b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/labeledUtil.kt similarity index 99% rename from kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/labeledUtil.kt rename to kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/labeledUtil.kt index 4e799cb43..e3b35facc 100644 --- a/kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/labeledUtil.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/labeledUtil.kt @@ -8,9 +8,9 @@ package space.kscience.kmath.functions import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Field -import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.algebra +import space.kscience.kmath.operations.invoke import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.jvm.JvmName diff --git a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/listConstructors.kt b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/listConstructors.kt new file mode 100644 index 000000000..e95361724 --- /dev/null +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/listConstructors.kt @@ -0,0 +1,92 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.operations.Ring + + +/** + * Constructs a [ListPolynomial] instance with provided [coefficients]. The collection of coefficients will be reversed + * if [reverse] parameter is true. + */ +@Suppress("FunctionName") +public fun ListPolynomial(coefficients: List, reverse: Boolean = false): ListPolynomial = + ListPolynomial(with(coefficients) { if (reverse) reversed() else this }) + +/** + * Constructs a [ListPolynomial] instance with provided [coefficients]. The collection of coefficients will be reversed + * if [reverse] parameter is true. + */ +@Suppress("FunctionName") +public fun ListPolynomial(vararg coefficients: C, reverse: Boolean = false): ListPolynomial = + ListPolynomial(with(coefficients) { if (reverse) reversed() else toList() }) + +/** + * Represents [this] constant as a [ListPolynomial]. + */ +public fun C.asListPolynomial() : ListPolynomial = ListPolynomial(listOf(this)) + + +// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available + +/** + * Constructs [ListRationalFunction] instance with numerator and denominator constructed with provided + * [numeratorCoefficients] and [denominatorCoefficients]. The both collections of coefficients will be reversed if + * [reverse] parameter is true. + */ +@Suppress("FunctionName") +public fun ListRationalFunction(numeratorCoefficients: List, denominatorCoefficients: List, reverse: Boolean = false): ListRationalFunction = + ListRationalFunction( + ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), + ListPolynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } ) + ) +/** + * Constructs [ListRationalFunction] instance with provided [numerator] and unit denominator. + */ +@Suppress("FunctionName") +public fun > A.ListRationalFunction(numerator: ListPolynomial): ListRationalFunction = + ListRationalFunction(numerator, ListPolynomial(listOf(one))) +/** + * Constructs [ListRationalFunction] instance with provided [numerator] and unit denominator. + */ +@Suppress("FunctionName") +public fun > ListRationalFunctionSpace.ListRationalFunction(numerator: ListPolynomial): ListRationalFunction = + ListRationalFunction(numerator, polynomialOne) +/** + * Constructs [ListRationalFunction] instance with numerator constructed with provided [numeratorCoefficients] and unit + * denominator. The collection of numerator coefficients will be reversed if [reverse] parameter is true. + */ +@Suppress("FunctionName") +public fun > A.ListRationalFunction(numeratorCoefficients: List, reverse: Boolean = false): ListRationalFunction = + ListRationalFunction( + ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), + ListPolynomial(listOf(one)) + ) +/** + * Constructs [ListRationalFunction] instance with numerator constructed with provided [numeratorCoefficients] and unit + * denominator. The collection of numerator coefficients will be reversed if [reverse] parameter is true. + */ +@Suppress("FunctionName") +public fun > ListRationalFunctionSpace.ListRationalFunction(numeratorCoefficients: List, reverse: Boolean = false): ListRationalFunction = + ListRationalFunction( + ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), + polynomialOne + ) + +/** + * Represents [this] constant as a rational function. + */ // FIXME: When context receivers will be ready, delete this function and uncomment the following two +public fun > C.asListRationalFunction(ring: A) : ListRationalFunction = ring.ListRationalFunction(asListPolynomial()) +///** +// * Represents [this] constant as a rational function. +// */ +//context(A) +//public fun > C.asListRationalFunction() : ListRationalFunction = ListRationalFunction(asListPolynomial()) +///** +// * Represents [this] constant as a rational function. +// */ +//context(ListRationalFunctionSpace) +//public fun > C.asListRationalFunction() : ListRationalFunction = ListRationalFunction(asListPolynomial()) \ No newline at end of file diff --git a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/listUtil.kt b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/listUtil.kt new file mode 100644 index 000000000..4f3f6d88e --- /dev/null +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/listUtil.kt @@ -0,0 +1,255 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.* +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract +import kotlin.math.max +import kotlin.math.pow + + +/** + * Creates a [ListPolynomialSpace] over a received ring. + */ +public inline val > A.listPolynomialSpace: ListPolynomialSpace + get() = ListPolynomialSpace(this) + +/** + * Creates a [ListPolynomialSpace]'s scope over a received ring. + */ // TODO: When context will be ready move [ListPolynomialSpace] and add [A] to context receivers of [block] +public inline fun , R> A.listPolynomialSpace(block: ListPolynomialSpace.() -> R): R { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return ListPolynomialSpace(this).block() +} + +/** + * Creates a [ScalableListPolynomialSpace] over a received scalable ring. + */ +public inline val A.scalableListPolynomialSpace: ScalableListPolynomialSpace where A : Ring, A : ScaleOperations + get() = ScalableListPolynomialSpace(this) + +/** + * Creates a [ScalableListPolynomialSpace]'s scope over a received scalable ring. + */ // TODO: When context will be ready move [ListPolynomialSpace] and add [A] to context receivers of [block] +public inline fun A.scalableListPolynomialSpace(block: ScalableListPolynomialSpace.() -> R): R where A : Ring, A : ScaleOperations { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return ScalableListPolynomialSpace(this).block() +} + +/** + * Creates a [ListRationalFunctionSpace] over a received ring. + */ +public inline val > A.listRationalFunctionSpace: ListRationalFunctionSpace + get() = ListRationalFunctionSpace(this) + +/** + * Creates a [ListRationalFunctionSpace]'s scope over a received ring. + */ // TODO: When context will be ready move [ListRationalFunctionSpace] and add [A] to context receivers of [block] +public inline fun , R> A.listRationalFunctionSpace(block: ListRationalFunctionSpace.() -> R): R { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return ListRationalFunctionSpace(this).block() +} + + +/** + * Evaluates value of [this] Double polynomial on provided Double argument. + */ +public fun ListPolynomial.substitute(arg: Double): Double = + coefficients.reduceIndexedOrNull { index, acc, c -> + acc + c * arg.pow(index) + } ?: .0 + +/** + * Evaluates value of [this] polynomial on provided argument. + * + * It is an implementation of [Horner's method](https://en.wikipedia.org/wiki/Horner%27s_method). + */ +public fun ListPolynomial.substitute(ring: Ring, arg: C): C = ring { + if (coefficients.isEmpty()) return zero + var result: C = coefficients.last() + for (j in coefficients.size - 2 downTo 0) { + result = (arg * result) + coefficients[j] + } + return result +} + +/** + * Substitutes provided polynomial [arg] into [this] polynomial. + * + * It is an implementation of [Horner's method](https://en.wikipedia.org/wiki/Horner%27s_method). + */ // TODO: To optimize boxing +public fun ListPolynomial.substitute(ring: Ring, arg: ListPolynomial) : ListPolynomial = + ring.listPolynomialSpace { + if (coefficients.isEmpty()) return zero + var result: ListPolynomial = coefficients.last().asPolynomial() + for (j in coefficients.size - 2 downTo 0) { + result = (arg * result) + coefficients[j] + } + return result + } + +/** + * Substitutes provided rational function [arg] into [this] polynomial. + * + * It is an implementation of [Horner's method](https://en.wikipedia.org/wiki/Horner%27s_method). + */ // TODO: To optimize boxing +public fun ListPolynomial.substitute(ring: Ring, arg: ListRationalFunction) : ListRationalFunction = + ring.listRationalFunctionSpace { + if (coefficients.isEmpty()) return zero + var result: ListRationalFunction = coefficients.last().asRationalFunction() + for (j in coefficients.size - 2 downTo 0) { + result = (arg * result) + coefficients[j] + } + return result + } + +/** + * Evaluates value of [this] Double rational function in provided Double argument. + */ +public fun ListRationalFunction.substitute(arg: Double): Double = + numerator.substitute(arg) / denominator.substitute(arg) + +/** + * Evaluates value of [this] polynomial for provided argument. + * + * It is an implementation of [Horner's method](https://en.wikipedia.org/wiki/Horner%27s_method). + */ +public fun ListRationalFunction.substitute(ring: Field, arg: C): C = ring { + numerator.substitute(ring, arg) / denominator.substitute(ring, arg) +} + +/** + * Substitutes provided polynomial [arg] into [this] rational function. + */ // TODO: To optimize boxing +public fun ListRationalFunction.substitute(ring: Ring, arg: ListPolynomial) : ListRationalFunction = + ring.listRationalFunctionSpace { + numerator.substitute(ring, arg) / denominator.substitute(ring, arg) + } + +/** + * Substitutes provided rational function [arg] into [this] rational function. + */ // TODO: To optimize boxing +public fun ListRationalFunction.substitute(ring: Ring, arg: ListRationalFunction) : ListRationalFunction = + ring.listRationalFunctionSpace { + numerator.substitute(ring, arg) / denominator.substitute(ring, arg) + } + +/** + * Represent [this] polynomial as a regular context-less function. + */ +public fun > ListPolynomial.asFunctionOver(ring: A): (C) -> C = { substitute(ring, it) } + +/** + * Represent [this] polynomial as a regular context-less function. + */ +public fun > ListPolynomial.asFunctionOfConstantOver(ring: A): (C) -> C = { substitute(ring, it) } + +/** + * Represent [this] polynomial as a regular context-less function. + */ +public fun > ListPolynomial.asFunctionOfPolynomialOver(ring: A): (ListPolynomial) -> ListPolynomial = { substitute(ring, it) } + +/** + * Represent [this] polynomial as a regular context-less function. + */ +public fun > ListPolynomial.asFunctionOfRationalFunctionOver(ring: A): (ListRationalFunction) -> ListRationalFunction = { substitute(ring, it) } + +/** + * Represent [this] rational function as a regular context-less function. + */ +public fun > ListRationalFunction.asFunctionOver(ring: A): (C) -> C = { substitute(ring, it) } + +/** + * Represent [this] rational function as a regular context-less function. + */ +public fun > ListRationalFunction.asFunctionOfConstantOver(ring: A): (C) -> C = { substitute(ring, it) } + +/** + * Represent [this] rational function as a regular context-less function. + */ +public fun > ListRationalFunction.asFunctionOfPolynomialOver(ring: A): (ListPolynomial) -> ListRationalFunction = { substitute(ring, it) } + +/** + * Represent [this] rational function as a regular context-less function. + */ +public fun > ListRationalFunction.asFunctionOfRationalFunctionOver(ring: A): (ListRationalFunction) -> ListRationalFunction = { substitute(ring, it) } + +/** + * Returns algebraic derivative of received polynomial. + */ +@UnstableKMathAPI +public fun ListPolynomial.derivative( + ring: A, +): ListPolynomial where A : Ring, A : NumericAlgebra = ring { + ListPolynomial( + buildList(max(0, coefficients.size - 1)) { + for (deg in 1 .. coefficients.lastIndex) add(number(deg) * coefficients[deg]) + } + ) +} + +/** + * Returns algebraic derivative of received polynomial of specified [order]. The [order] should be non-negative integer. + */ +@UnstableKMathAPI +public fun ListPolynomial.nthDerivative( + ring: A, + order: Int, +): ListPolynomial where A : Ring, A : NumericAlgebra = ring { + require(order >= 0) { "Order of derivative must be non-negative" } + ListPolynomial( + buildList(max(0, coefficients.size - order)) { + for (deg in order.. coefficients.lastIndex) + add((deg - order + 1 .. deg).fold(coefficients[deg]) { acc, d -> acc * number(d) }) + } + ) +} + +/** + * Returns algebraic antiderivative of received polynomial. + */ +@UnstableKMathAPI +public fun ListPolynomial.antiderivative( + ring: A, +): ListPolynomial where A : Field, A : NumericAlgebra = ring { + ListPolynomial( + buildList(coefficients.size + 1) { + add(zero) + coefficients.mapIndexedTo(this) { index, t -> t / number(index + 1) } + } + ) +} + +/** + * Returns algebraic antiderivative of received polynomial of specified [order]. The [order] should be non-negative integer. + */ +@UnstableKMathAPI +public fun ListPolynomial.nthAntiderivative( + ring: A, + order: Int, +): ListPolynomial where A : Field, A : NumericAlgebra = ring { + require(order >= 0) { "Order of antiderivative must be non-negative" } + ListPolynomial( + buildList(coefficients.size + order) { + repeat(order) { add(zero) } + coefficients.mapIndexedTo(this) { index, c -> (1..order).fold(c) { acc, i -> acc / number(index + i) } } + } + ) +} + +/** + * Computes a definite integral of [this] polynomial in the specified [range]. + */ +@UnstableKMathAPI +public fun > ListPolynomial.integrate( + ring: Field, + range: ClosedRange, +): C = ring { + val antiderivative = antiderivative(ring) + antiderivative.substitute(ring, range.endInclusive) - antiderivative.substitute(ring, range.start) +} \ No newline at end of file diff --git a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/misc.kt b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/misc.kt new file mode 100644 index 000000000..76f1c294e --- /dev/null +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/misc.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.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-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/numberedConstructors.kt b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/numberedConstructors.kt similarity index 100% rename from kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/numberedConstructors.kt rename to kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/numberedConstructors.kt diff --git a/kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/numberedUtil.kt b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/numberedUtil.kt similarity index 100% rename from kmath-polynomialX/src/commonMain/kotlin/space.kscience.kmath.functions/numberedUtil.kt rename to kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/numberedUtil.kt diff --git a/kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt similarity index 99% rename from kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt rename to kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt index 081cf06e4..80476050b 100644 --- a/kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt @@ -6,13 +6,13 @@ package space.kscience.kmath.functions import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.algebra -import space.kscience.kmath.operations.invoke 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 diff --git a/kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt similarity index 99% rename from kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt rename to kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt index d2d417a02..bde1386da 100644 --- a/kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt @@ -11,15 +11,15 @@ 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.o +import space.kscience.kmath.functions.testUtils.iota import space.kscience.kmath.functions.testUtils.m -import kotlin.test.* +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 space.kscience.kmath.functions.testUtils.t -import space.kscience.kmath.functions.testUtils.s -import space.kscience.kmath.functions.testUtils.iota +import kotlin.test.* // TODO: Тесты на конвертацию. diff --git a/kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt similarity index 99% rename from kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt rename to kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt index 37329a318..88ee1cbb8 100644 --- a/kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt @@ -6,16 +6,15 @@ package space.kscience.kmath.functions import space.kscience.kmath.expressions.Symbol -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.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 -import space.kscience.kmath.functions.testUtils.x -import space.kscience.kmath.functions.testUtils.y -import space.kscience.kmath.functions.testUtils.iota -import space.kscience.kmath.functions.testUtils.assertEquals class LabeledPolynomialUtilTest { @Test diff --git a/kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt similarity index 100% rename from kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt rename to kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt diff --git a/kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt similarity index 100% rename from kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt rename to kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt diff --git a/kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt similarity index 100% rename from kmath-polynomialX/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt rename to kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt diff --git a/settings.gradle.kts b/settings.gradle.kts index 543d08001..bdd83d04e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -27,8 +27,8 @@ include( ":kmath-coroutines", ":kmath-functions", ":test-utils-functions", - ":kmath-polynomialX", - ":test-utils-polynomialX", + ":kmath-polynomial", + ":test-utils-polynomial", ":kmath-histograms", ":kmath-commons", ":kmath-viktor", diff --git a/test-utils-polynomialX/build.gradle.kts b/test-utils-polynomial/build.gradle.kts similarity index 63% rename from test-utils-polynomialX/build.gradle.kts rename to test-utils-polynomial/build.gradle.kts index f20e1b8bb..e10e1f2b1 100644 --- a/test-utils-polynomialX/build.gradle.kts +++ b/test-utils-polynomial/build.gradle.kts @@ -7,9 +7,7 @@ kotlin.sourceSets { commonMain { dependencies { api(projects.kmathCore) - api(projects.kmathFunctions) - api(projects.testUtilsFunctions) - api(projects.kmathPolynomialX) + api(projects.kmathPolynomial) api(kotlin("test")) } } diff --git a/test-utils-polynomialX/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/BufferUtils.kt b/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/BufferUtils.kt similarity index 100% rename from test-utils-polynomialX/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/BufferUtils.kt rename to test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/BufferUtils.kt diff --git a/test-utils-polynomialX/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt b/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt similarity index 100% rename from test-utils-polynomialX/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt rename to test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt diff --git a/test-utils-polynomialX/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/misc.kt b/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/misc.kt similarity index 100% rename from test-utils-polynomialX/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/misc.kt rename to test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/misc.kt -- 2.34.1 From f726e6d0f17698dd47d6060212c8a6a04257f726 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Mon, 11 Jul 2022 23:32:15 +0300 Subject: [PATCH 124/275] Minimise appearance of new feature, leave only upgrades. --- .../kmath/functions/ListPolynomial.kt | 387 -------- .../kscience/kmath/functions/Piecewise.kt | 22 +- .../kscience/kmath/functions/Polynomial.kt | 629 +++++-------- .../kscience/kmath/functions/algebraicStub.kt | 95 -- .../kmath/functions/listConstructors.kt | 92 -- .../kscience/kmath/functions/listUtil.kt | 255 ------ .../space/kscience/kmath/functions/misc.kt | 22 - .../kmath/functions/polynomialConstructors.kt | 28 + .../kmath/functions/polynomialUtil.kt | 111 +++ .../kmath/functions/AlgebraicStubTest.kt | 460 ---------- .../kmath/functions/ListPolynomialTest.kt | 251 +----- .../kmath/functions/ListPolynomialUtilTest.kt | 850 +----------------- .../functions/testUtils/IntModuloUtils.kt | 13 +- 13 files changed, 376 insertions(+), 2839 deletions(-) delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialConstructors.kt create mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt deleted file mode 100644 index 76e1a6bb6..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt +++ /dev/null @@ -1,387 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -@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. - */ - public val coefficients: List -) : Polynomial { - 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 - .toMutableList() - .apply { - for (deg in indices) this[deg] = this[deg] * 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 - .toMutableList() - .apply { - for (deg in indices) this[deg] = this@times * this[deg] - } - ) - } - - /** - * Returns sum of the constant represented as a polynomial and the polynomial. - */ - public 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 - .toMutableList() - .apply { - for (deg in indices) this[deg] = this@times * this[deg] - } - ) - - /** - * Returns sum of the constant represented as a polynomial and the polynomial. - */ - public 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 - .toMutableList() - .apply { - for (deg in indices) this[deg] = this[deg] * 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-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt index 612b00535..cfd21d552 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt @@ -27,10 +27,10 @@ public fun interface Piecewise { * @property pieces An ordered list of range-polynomial pairs. The list does not in general guarantee that there are no * "holes" in it. */ -public interface PiecewisePolynomial> : Piecewise> { - public val pieces: Collection, ListPolynomial>> +public interface PiecewisePolynomial> : Piecewise> { + public val pieces: Collection, Polynomial>> - override fun findPiece(arg: T): ListPolynomial? + override fun findPiece(arg: T): Polynomial? } /** @@ -38,11 +38,11 @@ public interface PiecewisePolynomial> : Piecewise> PiecewisePolynomial( - pieces: Collection, ListPolynomial>>, + pieces: Collection, Polynomial>>, ): PiecewisePolynomial = object : PiecewisePolynomial { - override val pieces: Collection, ListPolynomial>> = pieces + override val pieces: Collection, Polynomial>> = pieces - override fun findPiece(arg: T): ListPolynomial? = pieces.firstOrNull { arg in it.first }?.second + override fun findPiece(arg: T): Polynomial? = pieces.firstOrNull { arg in it.first }?.second } /** @@ -50,10 +50,10 @@ public fun > PiecewisePolynomial( * The pieces search is logarithmic. */ private class OrderedPiecewisePolynomial>( - override val pieces: List, ListPolynomial>>, + override val pieces: List, Polynomial>>, ) : PiecewisePolynomial { - override fun findPiece(arg: T): ListPolynomial? { + override fun findPiece(arg: T): Polynomial? { val index = pieces.binarySearch { (range, _) -> when { arg >= range.endInclusive -> -1 @@ -74,7 +74,7 @@ private class OrderedPiecewisePolynomial>( */ public class PiecewiseBuilder>(delimiter: T) { private val delimiters: MutableList = arrayListOf(delimiter) - private val pieces: MutableList> = arrayListOf() + private val pieces: MutableList> = arrayListOf() /** * Dynamically adds a piece to the right side (beyond maximum argument value of previous piece) @@ -82,7 +82,7 @@ public class PiecewiseBuilder>(delimiter: T) { * @param right new rightmost position. If is less than current rightmost position, an error is thrown. * @param piece the sub-function. */ - public fun putRight(right: T, piece: ListPolynomial) { + public fun putRight(right: T, piece: Polynomial) { require(right > delimiters.last()) { "New delimiter should be to the right of old one" } delimiters += right pieces += piece @@ -94,7 +94,7 @@ public class PiecewiseBuilder>(delimiter: T) { * @param left the new leftmost position. If is less than current rightmost position, an error is thrown. * @param piece the sub-function. */ - public fun putLeft(left: T, piece: ListPolynomial) { + public fun putLeft(left: T, piece: Polynomial) { require(left < delimiters.first()) { "New delimiter should be to the left of old one" } delimiters.add(0, left) pieces.add(0, piece) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 61ea5a342..fec4776d9 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -3,500 +3,299 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ +@file:Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") + package space.kscience.kmath.functions import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.invoke -import kotlin.js.JsName -import kotlin.jvm.JvmName +import kotlin.jvm.JvmInline +import kotlin.math.max +import kotlin.math.min /** - * Abstraction of polynomials. - */ -public interface Polynomial - -/** - * Abstraction of ring of polynomials of type [P] over ring of constants of type [C]. + * Represents univariate polynomial that stores its coefficients in a [List]. * - * @param C the type of constants. Polynomials have them as coefficients in their terms. - * @param P the type of polynomials. + * @param C the type of constants. */ -@Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") // FIXME: Waiting for KT-31420 -public interface PolynomialSpace> : Ring

{ +@JvmInline +public value class Polynomial( /** - * 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]. + * 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. */ - 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]. - */ - 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]. - */ - public operator fun C.times(other: Int): C + 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>( /** - * 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]. + * Underlying ring of constants. Its operations on constants are inherited by local operations on constants. */ - 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]. - */ - 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]. - */ - 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 + public val ring: A, +) : Ring> { /** * Instance of zero constant (zero of the underlying ring). */ - public val constantZero: C + public val constantZero: C get() = ring.zero /** * Instance of unit constant (unit of the underlying ring). */ - public val constantOne: C + public val constantOne: C get() = ring.one /** * Returns sum of the constant represented as a polynomial and the polynomial. */ - public operator fun C.plus(other: P): P + public operator fun C.plus(other: Polynomial): Polynomial = + with(ring) { + with(other.coefficients) { + if (isEmpty()) Polynomial(listOf(this@plus)) + else Polynomial( + toMutableList() + .apply { + val result = if (size == 0) this@plus else this@plus + get(0) + + if (size == 0) add(result) + else this[0] = result + } + ) + } + } /** * Returns difference between the constant represented as a polynomial and the polynomial. */ - public operator fun C.minus(other: P): P + public operator fun C.minus(other: Polynomial): Polynomial = + with(ring) { + with(other.coefficients) { + if (isEmpty()) Polynomial(listOf(this@minus)) + else Polynomial( + toMutableList() + .apply { + (1..lastIndex).forEach { this[it] = -this[it] } + + val result = if (size == 0) this@minus else this@minus - get(0) + + if (size == 0) add(result) + else this[0] = result + } + ) + } + } /** * Returns product of the constant represented as a polynomial and the polynomial. */ - public operator fun C.times(other: P): P + public operator fun C.times(other: Polynomial): Polynomial = + with(ring) { + Polynomial( + other.coefficients + .toMutableList() + .apply { + for (deg in indices) this[deg] = this@times * this[deg] + } + ) + } /** * Returns sum of the constant represented as a polynomial and the polynomial. */ - public operator fun P.plus(other: C): P + public operator fun Polynomial.plus(other: C): Polynomial = + with(ring) { + with(coefficients) { + if (isEmpty()) Polynomial(listOf(other)) + else Polynomial( + toMutableList() + .apply { + val result = if (size == 0) other else get(0) + other + + if (size == 0) add(result) + else this[0] = result + } + ) + } + } /** * Returns difference between the constant represented as a polynomial and the polynomial. */ - public operator fun P.minus(other: C): P + public operator fun Polynomial.minus(other: C): Polynomial = + with(ring) { + with(coefficients) { + if (isEmpty()) Polynomial(listOf(-other)) + else Polynomial( + toMutableList() + .apply { + val result = if (size == 0) other else get(0) - other + + if (size == 0) add(result) + else this[0] = result + } + ) + } + } /** * Returns product of the constant represented as a polynomial and the polynomial. */ - public operator fun P.times(other: C): P + public operator fun Polynomial.times(other: C): Polynomial = + with(ring) { + Polynomial( + coefficients + .toMutableList() + .apply { + for (deg in indices) this[deg] = this[deg] * other + } + ) + } /** * Converts the constant [value] to polynomial. */ - public fun number(value: C): P = one * value + public fun number(value: C): Polynomial = Polynomial(listOf(value)) /** * Converts the constant to polynomial. */ - public fun C.asPolynomial(): P = number(this) + public fun C.asPolynomial(): Polynomial = 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 + public override operator fun Polynomial.unaryMinus(): Polynomial = + with(ring) { + Polynomial(coefficients.map { -it }) + } /** * Returns sum of the polynomials. */ - public override operator fun P.plus(other: P): P + public override operator fun Polynomial.plus(other: Polynomial): Polynomial { + with(ring) { + val thisDegree = degree + val otherDegree = other.degree + return Polynomial( + List(max(thisDegree, otherDegree) + 1) { + when { + it > thisDegree -> other.coefficients[it] + it > otherDegree -> coefficients[it] + else -> coefficients[it] + other.coefficients[it] + } + } + ) + } + } /** * Returns difference of the polynomials. */ - public override operator fun P.minus(other: P): P + public override operator fun Polynomial.minus(other: Polynomial): Polynomial { + with(ring) { + val thisDegree = degree + val otherDegree = other.degree + return Polynomial( + List(max(thisDegree, otherDegree) + 1) { + when { + it > thisDegree -> -other.coefficients[it] + it > otherDegree -> coefficients[it] + else -> coefficients[it] - other.coefficients[it] + } + } + ) + } + } /** * Returns product of the polynomials. */ - public override operator fun P.times(other: P): P + public override operator fun Polynomial.times(other: Polynomial): Polynomial { + with(ring) { + val thisDegree = degree + val otherDegree = other.degree + return Polynomial( + List(thisDegree + otherDegree + 1) { d -> + (max(0, d - otherDegree)..min(thisDegree, d)) + .map { coefficients[it] * other.coefficients[d - it] } + .reduce { acc, rational -> acc + rational } + } + ) + } + } /** * Raises [arg] to the integer power [exponent]. - */ - public override fun power(arg: P, exponent: UInt) : P = exponentiateBySquaring(arg, exponent) + */ // TODO: To optimize boxing + override fun power(arg: Polynomial, exponent: UInt): Polynomial = exponentiateBySquaring(arg, exponent) /** * Instance of zero polynomial (zero of the polynomial ring). */ - public override val zero: P + override val zero: Polynomial = Polynomial(emptyList()) /** * Instance of unit polynomial (unit of the polynomial ring). */ - public override val one: P + override val one: Polynomial by lazy { Polynomial(listOf(constantOne)) } /** * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is * zero, degree is -1. */ - public val P.degree: Int + public val Polynomial.degree: Int get() = coefficients.lastIndex - override fun add(left: P, right: P): P = left + right - override fun multiply(left: P, right: P): P = left * right + override fun add(left: Polynomial, right: Polynomial): Polynomial = left + right + override fun multiply(left: Polynomial, right: Polynomial): Polynomial = left * right + + // TODO: When context receivers will be ready move all of this substitutions and invocations to utilities with + // [ListPolynomialSpace] as a context receiver + /** + * Evaluates value of [this] polynomial on provided [argument]. + */ + public inline fun Polynomial.substitute(argument: C): C = substitute(ring, argument) + + /** + * Represent [this] polynomial as a regular context-less function. + */ + public inline fun Polynomial.asFunction(): (C) -> C = asFunctionOver(ring) + + /** + * Evaluates value of [this] polynomial on provided [argument]. + */ + public inline operator fun Polynomial.invoke(argument: C): C = substitute(ring, argument) } /** - * 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. + * Space of polynomials constructed over ring. * - * @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. + * @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]. */ -@Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 -public interface PolynomialSpaceOverRing, A: Ring> : 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]. - */ - 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]. - */ - 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]. - */ - 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]. - */ - 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]. - */ - 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]. - */ - 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 +public class ScalableListPolynomialSpace( + ring: A, +) : ListPolynomialSpace(ring), ScaleOperations> where A : Ring, A : ScaleOperations { + override fun scale(a: Polynomial, value: Double): Polynomial = + ring { Polynomial(a.coefficients.map { scale(it, value) }) } } - -/** - * 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") - 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") - 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") - 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") - 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") - 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") - 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") - 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") - 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") - 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") - 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") - 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") - 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-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt index b40aa4775..5eb1af4dc 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt @@ -9,101 +9,6 @@ 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]. diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt deleted file mode 100644 index e95361724..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.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-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt deleted file mode 100644 index 4f3f6d88e..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.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-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt deleted file mode 100644 index 76f1c294e..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.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-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialConstructors.kt new file mode 100644 index 000000000..ff04607a7 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialConstructors.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + + +/** + * Constructs a [Polynomial] 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): Polynomial = + Polynomial(with(coefficients) { if (reverse) reversed() else this }) + +/** + * Constructs a [Polynomial] instance with provided [coefficients]. The collection of coefficients will be reversed + * if [reverse] parameter is true. + */ +@Suppress("FunctionName") +public fun ListPolynomial(vararg coefficients: C, reverse: Boolean = false): Polynomial = + Polynomial(with(coefficients) { if (reverse) reversed() else toList() }) + +/** + * Represents [this] constant as a [Polynomial]. + */ +public fun C.asListPolynomial() : Polynomial = Polynomial(listOf(this)) \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt new file mode 100644 index 000000000..fc3a728df --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt @@ -0,0 +1,111 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.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() +} + + +/** + * Evaluates value of [this] Double polynomial on provided Double argument. + */ +public fun Polynomial.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 Polynomial.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 +} + +/** + * Represent [this] polynomial as a regular context-less function. + */ +public fun > Polynomial.asFunctionOver(ring: A): (C) -> C = { substitute(ring, it) } + +/** + * Returns algebraic derivative of received polynomial. + */ +@UnstableKMathAPI +public fun Polynomial.derivative( + ring: A, +): Polynomial where A : Ring, A : NumericAlgebra = ring { + Polynomial( + buildList(max(0, coefficients.size - 1)) { + for (deg in 1 .. coefficients.lastIndex) add(number(deg) * coefficients[deg]) + } + ) +} + +/** + * Returns algebraic antiderivative of received polynomial. + */ +@UnstableKMathAPI +public fun Polynomial.antiderivative( + ring: A, +): Polynomial where A : Field, A : NumericAlgebra = ring { + Polynomial( + buildList(coefficients.size + 1) { + add(zero) + coefficients.mapIndexedTo(this) { index, t -> t / number(index + 1) } + } + ) +} + +/** + * Computes a definite integral of [this] polynomial in the specified [range]. + */ +@UnstableKMathAPI +public fun > Polynomial.integrate( + ring: Field, + range: ClosedRange, +): C { + val antiderivative = antiderivative(ring) + return ring { antiderivative.substitute(ring, range.endInclusive) - antiderivative.substitute(ring, range.start) } +} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt index 487cd9ee1..5782292b1 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt @@ -26,286 +26,6 @@ object ExprRing : Field { } 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 { @@ -406,184 +126,4 @@ class AlgebraicStubTest { ) } } - @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-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt index e7d8dfd8c..117ffb579 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt @@ -7,252 +7,11 @@ 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 space.kscience.kmath.functions.testUtils.* 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 { @@ -338,12 +97,12 @@ class ListPolynomialTest { IntModuloRing(35).listPolynomialSpace { assertEquals( ListPolynomial(34, 2, 1, 20, 2), - ListPolynomial(22, 26, 13, 15, 26) * 27.asConstant(), + ListPolynomial(22, 26, 13, 15, 26) * m(27), "test 1" ) assertEquals( ListPolynomial(0, 0, 0, 0, 0), - ListPolynomial(7, 0, 49, 21, 14) * 15.asConstant(), + ListPolynomial(7, 0, 49, 21, 14) * m(15), "test 2" ) } @@ -433,12 +192,12 @@ class ListPolynomialTest { IntModuloRing(35).listPolynomialSpace { assertEquals( ListPolynomial(34, 2, 1, 20, 2), - 27 * ListPolynomial(22, 26, 13, 15, 26), + m(27) * ListPolynomial(22, 26, 13, 15, 26), "test 1" ) assertEquals( ListPolynomial(0, 0, 0, 0, 0), - 15 * ListPolynomial(7, 0, 49, 21, 14), + m(15) * ListPolynomial(7, 0, 49, 21, 14), "test 2" ) } diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt index 339643d02..153b0134b 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt @@ -5,11 +5,9 @@ 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 space.kscience.kmath.misc.UnstableKMathAPI import kotlin.test.Test import kotlin.test.assertEquals @@ -88,754 +86,6 @@ class ListPolynomialUtilTest { ) } @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)), @@ -859,55 +109,6 @@ class ListPolynomialUtilTest { ) } @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)), @@ -930,53 +131,4 @@ class ListPolynomialUtilTest { "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/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt b/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt index 4b65fbea1..997a966a7 100644 --- a/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt +++ b/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt @@ -5,15 +5,14 @@ package space.kscience.kmath.functions.testUtils -import space.kscience.kmath.functions.ListPolynomial +import space.kscience.kmath.functions.Polynomial import space.kscience.kmath.functions.ListPolynomialSpace -import space.kscience.kmath.functions.PolynomialSpaceOverRing -public fun ListPolynomialSpace.ListPolynomial(vararg coefs: Int): ListPolynomial = - ListPolynomial(coefs.map { IntModulo(it, ring.modulus) }) -public fun IntModuloRing.ListPolynomial(vararg coefs: Int): ListPolynomial = - ListPolynomial(coefs.map { IntModulo(it, modulus) }) +public fun ListPolynomialSpace.ListPolynomial(vararg coefs: Int): Polynomial = + Polynomial(coefs.map { IntModulo(it, ring.modulus) }) +public fun IntModuloRing.ListPolynomial(vararg coefs: Int): Polynomial = + Polynomial(coefs.map { IntModulo(it, modulus) }) public fun IntModuloRing.m(arg: Int): IntModulo = IntModulo(arg, modulus) -public fun PolynomialSpaceOverRing.m(arg: Int): IntModulo = IntModulo(arg, ring.modulus) \ No newline at end of file +public fun ListPolynomialSpace.m(arg: Int): IntModulo = IntModulo(arg, ring.modulus) \ No newline at end of file -- 2.34.1 From 6ff79e28ac0b34e74cbec682866610492425a157 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 12 Jul 2022 00:57:44 +0300 Subject: [PATCH 125/275] Fix names, references, etc. --- .../kscience/kmath/functions/Polynomial.kt | 6 +- .../kmath/functions/polynomialConstructors.kt | 6 +- .../kmath/functions/polynomialUtil.kt | 24 +- .../kmath/interpolation/LinearInterpolator.kt | 4 +- .../kmath/interpolation/SplineInterpolator.kt | 4 +- .../kmath/functions/ListPolynomialTest.kt | 303 ------------------ .../kmath/functions/ListPolynomialUtilTest.kt | 134 -------- .../kmath/functions/PolynomialTest.kt | 303 ++++++++++++++++++ .../kmath/functions/PolynomialUtilTest.kt | 134 ++++++++ .../kmath/integration/SplineIntegralTest.kt | 4 +- .../functions/LabeledPolynomialUtilTest.kt | 1 + .../functions/testUtils/IntModuloUtils.kt | 8 +- .../kmath/functions/testUtils/IntModulo.kt | 133 ++++++++ .../functions/testUtils/IntModuloUtils.kt | 20 ++ .../kmath/functions/testUtils/NTMisc.kt | 29 ++ .../kmath/functions/testUtils/Rational.kt | 177 ++++++++++ .../kmath/functions/testUtils/assertion.kt | 1 - 17 files changed, 825 insertions(+), 466 deletions(-) delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt create mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt create mode 100644 test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt create mode 100644 test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt create mode 100644 test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/NTMisc.kt create mode 100644 test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index fec4776d9..061f556f6 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -59,7 +59,7 @@ public value class Polynomial( * @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 open class PolynomialSpace>( /** * Underlying ring of constants. Its operations on constants are inherited by local operations on constants. */ @@ -293,9 +293,9 @@ public open class ListPolynomialSpace>( * @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( +public class ScalablePolynomialSpace( ring: A, -) : ListPolynomialSpace(ring), ScaleOperations> where A : Ring, A : ScaleOperations { +) : PolynomialSpace(ring), ScaleOperations> where A : Ring, A : ScaleOperations { override fun scale(a: Polynomial, value: Double): Polynomial = ring { Polynomial(a.coefficients.map { scale(it, value) }) } } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialConstructors.kt index ff04607a7..2da9ea6f5 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialConstructors.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialConstructors.kt @@ -11,7 +11,7 @@ package space.kscience.kmath.functions * if [reverse] parameter is true. */ @Suppress("FunctionName") -public fun ListPolynomial(coefficients: List, reverse: Boolean = false): Polynomial = +public fun Polynomial(coefficients: List, reverse: Boolean = false): Polynomial = Polynomial(with(coefficients) { if (reverse) reversed() else this }) /** @@ -19,10 +19,10 @@ public fun ListPolynomial(coefficients: List, reverse: Boolean = false): * if [reverse] parameter is true. */ @Suppress("FunctionName") -public fun ListPolynomial(vararg coefficients: C, reverse: Boolean = false): Polynomial = +public fun Polynomial(vararg coefficients: C, reverse: Boolean = false): Polynomial = Polynomial(with(coefficients) { if (reverse) reversed() else toList() }) /** * Represents [this] constant as a [Polynomial]. */ -public fun C.asListPolynomial() : Polynomial = Polynomial(listOf(this)) \ No newline at end of file +public fun C.asPolynomial() : Polynomial = Polynomial(listOf(this)) \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt index fc3a728df..0e1259bee 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt @@ -14,31 +14,31 @@ import kotlin.math.pow /** - * Creates a [ListPolynomialSpace] over a received ring. + * Creates a [PolynomialSpace] over a received ring. */ -public inline val > A.listPolynomialSpace: ListPolynomialSpace - get() = ListPolynomialSpace(this) +public inline val > A.polynomialSpace: PolynomialSpace + get() = PolynomialSpace(this) /** - * Creates a [ListPolynomialSpace]'s scope over a received ring. + * Creates a [PolynomialSpace]'s scope over a received ring. */ // TODO: When context will be ready move [ListPolynomialSpace] and add [A] to context receivers of [block] -public inline fun , R> A.listPolynomialSpace(block: ListPolynomialSpace.() -> R): R { +public inline fun , R> A.polynomialSpace(block: PolynomialSpace.() -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return ListPolynomialSpace(this).block() + return PolynomialSpace(this).block() } /** - * Creates a [ScalableListPolynomialSpace] over a received scalable ring. + * Creates a [ScalablePolynomialSpace] over a received scalable ring. */ -public inline val A.scalableListPolynomialSpace: ScalableListPolynomialSpace where A : Ring, A : ScaleOperations - get() = ScalableListPolynomialSpace(this) +public inline val A.scalablePolynomialSpace: ScalablePolynomialSpace where A : Ring, A : ScaleOperations + get() = ScalablePolynomialSpace(this) /** - * Creates a [ScalableListPolynomialSpace]'s scope over a received scalable ring. + * Creates a [ScalablePolynomialSpace]'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 { +public inline fun A.scalablePolynomialSpace(block: ScalablePolynomialSpace.() -> R): R where A : Ring, A : ScaleOperations { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return ScalableListPolynomialSpace(this).block() + return ScalablePolynomialSpace(this).block() } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt index b55f16cf2..34d7bcf41 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt @@ -7,7 +7,7 @@ package space.kscience.kmath.interpolation import space.kscience.kmath.data.XYColumnarData import space.kscience.kmath.functions.PiecewisePolynomial -import space.kscience.kmath.functions.ListPolynomial +import space.kscience.kmath.functions.Polynomial import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.invoke @@ -32,7 +32,7 @@ public class LinearInterpolator>(override val algebra: Field>( val x02 = x0 * x0 val x03 = x02 * x0 //Shift coefficients to represent absolute polynomial instead of one with an offset - val polynomial = ListPolynomial( + val polynomial = Polynomial( a - b * x0 + c * x02 - d * x03, b - 2 * c * x0 + 3 * d * x02, c - 3 * d * x0, diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt deleted file mode 100644 index 117ffb579..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -@file:Suppress("LocalVariableName") - -package space.kscience.kmath.functions - -import space.kscience.kmath.functions.testUtils.* -import kotlin.test.* - - -class ListPolynomialTest { - @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) * m(27), - "test 1" - ) - assertEquals( - ListPolynomial(0, 0, 0, 0, 0), - ListPolynomial(7, 0, 49, 21, 14) * m(15), - "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), - m(27) * ListPolynomial(22, 26, 13, 15, 26), - "test 1" - ) - assertEquals( - ListPolynomial(0, 0, 0, 0, 0), - m(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-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt deleted file mode 100644 index 153b0134b..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions - -import space.kscience.kmath.functions.testUtils.Rational -import space.kscience.kmath.functions.testUtils.RationalField -import space.kscience.kmath.misc.UnstableKMathAPI -import kotlin.test.Test -import kotlin.test.assertEquals - - -@OptIn(UnstableKMathAPI::class) -class 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_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_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" - ) - } -} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt new file mode 100644 index 000000000..7e0c6cdf2 --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt @@ -0,0 +1,303 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +@file:Suppress("LocalVariableName") + +package space.kscience.kmath.functions + +import space.kscience.kmath.functions.testUtils.* +import kotlin.test.* + + +class PolynomialTest { + @Test + fun test_Polynomial_Constant_plus() { + RationalField.polynomialSpace { + assertEquals( + Polynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)), + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + Rational(-3), + "test 1" + ) + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + Rational(2), + "test 2" + ) + assertEquals( + Polynomial(Rational(0)), + Polynomial(Rational(-2)) + Rational(2), + "test 3" + ) + assertEquals( + Polynomial(Rational(0)), + Polynomial() + Rational(0), + "test 4" + ) + assertEquals( + Polynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), + Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + Rational(1), + "test 5" + ) + assertEquals( + Polynomial(Rational(-1)), + Polynomial(Rational(-2)) + Rational(1), + "test 6" + ) + assertEquals( + Polynomial(Rational(2)), + Polynomial() + Rational(2), + "test 7" + ) + } + } + @Test + fun test_Polynomial_Constant_minus() { + RationalField.polynomialSpace { + assertEquals( + Polynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - Rational(-3), + "test 1" + ) + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + Polynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - Rational(2), + "test 2" + ) + assertEquals( + Polynomial(Rational(0)), + Polynomial(Rational(2)) - Rational(2), + "test 3" + ) + assertEquals( + Polynomial(Rational(0)), + Polynomial() - Rational(0), + "test 4" + ) + assertEquals( + Polynomial(Rational(1), Rational(0), Rational(0), Rational(0)), + Polynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - Rational(1), + "test 5" + ) + assertEquals( + Polynomial(Rational(1)), + Polynomial(Rational(2)) - Rational(1), + "test 6" + ) + assertEquals( + Polynomial(Rational(-2)), + Polynomial() - Rational(2), + "test 7" + ) + } + } + @Test + fun test_Polynomial_Constant_times() { + IntModuloRing(35).polynomialSpace { + assertEquals( + Polynomial(34, 2, 1, 20, 2), + Polynomial(22, 26, 13, 15, 26) * m(27), + "test 1" + ) + assertEquals( + Polynomial(0, 0, 0, 0, 0), + Polynomial(7, 0, 49, 21, 14) * m(15), + "test 2" + ) + } + } + @Test + fun test_Constant_Polynomial_plus() { + RationalField.polynomialSpace { + assertEquals( + Polynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)), + Rational(-3) + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)), + "test 1" + ) + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + Rational(2) + Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 2" + ) + assertEquals( + Polynomial(Rational(0)), + Rational(2) + Polynomial(Rational(-2)), + "test 3" + ) + assertEquals( + Polynomial(Rational(0)), + Rational(0) + Polynomial(), + "test 4" + ) + assertEquals( + Polynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), + Rational(1) + Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 5" + ) + assertEquals( + Polynomial(Rational(-1)), + Rational(1) + Polynomial(Rational(-2)), + "test 6" + ) + assertEquals( + Polynomial(Rational(2)), + Rational(2) + Polynomial(), + "test 7" + ) + } + } + @Test + fun test_Constant_Polynomial_minus() { + RationalField.polynomialSpace { + assertEquals( + Polynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), + Rational(3) - Polynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7)), + "test 1" + ) + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + Rational(-2) - Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 2" + ) + assertEquals( + Polynomial(Rational(0)), + Rational(-2) - Polynomial(Rational(-2)), + "test 3" + ) + assertEquals( + Polynomial(Rational(0)), + Rational(0) - Polynomial(), + "test 4" + ) + assertEquals( + Polynomial(Rational(1), Rational(0), Rational(0), Rational(0)), + Rational(-1) - Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 5" + ) + assertEquals( + Polynomial(Rational(1)), + Rational(-1) - Polynomial(Rational(-2)), + "test 6" + ) + assertEquals( + Polynomial(Rational(-2)), + Rational(-2) - Polynomial(), + "test 7" + ) + } + } + @Test + fun test_Constant_Polynomial_times() { + IntModuloRing(35).polynomialSpace { + assertEquals( + Polynomial(34, 2, 1, 20, 2), + m(27) * Polynomial(22, 26, 13, 15, 26), + "test 1" + ) + assertEquals( + Polynomial(0, 0, 0, 0, 0), + m(15) * Polynomial(7, 0, 49, 21, 14), + "test 2" + ) + } + } + @Test + fun test_Polynomial_unaryMinus() { + RationalField.polynomialSpace { + assertEquals( + Polynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7)), + -Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)), + "test 1" + ) + assertEquals( + Polynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7), Rational(0), Rational(0)), + -Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7), Rational(0), Rational(0)), + "test 2" + ) + } + } + @Test + fun test_Polynomial_Polynomial_plus() { + RationalField.polynomialSpace { + // (5/9 - 8/9 x - 8/7 x^2) + (-5/7 + 5/1 x + 5/8 x^2) ?= -10/63 + 37/9 x - 29/56 x^2 + assertEquals( + Polynomial(Rational(-10, 63), Rational(37, 9), Rational(-29, 56)), + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + + Polynomial(Rational(-5, 7), Rational(5, 1), Rational(5, 8)), + "test 1" + ) + // (-2/9 - 8/3 x) + (0 + 9/4 x + 2/4 x^2) ?= -2/9 - 5/12 x + 2/4 x^2 + assertEquals( + Polynomial(Rational(-2, 9), Rational(-5, 12), Rational(2, 4)), + Polynomial(Rational(-2, 9), Rational(-8, 3)) + + Polynomial(Rational(0), Rational(9, 4), Rational(2, 4)), + "test 2" + ) + // (-4/7 - 2/6 x + 0 x^2 + 0 x^3) + (-6/3 - 7/2 x + 2/3 x^2) ?= -18/7 - 23/6 x + 2/3 x^2 + assertEquals( + Polynomial(Rational(-18, 7), Rational(-23, 6), Rational(2, 3), Rational(0)), + Polynomial(Rational(-4, 7), Rational(-2, 6), Rational(0), Rational(0)) + + Polynomial(Rational(-6, 3), Rational(-7, 2), Rational(2, 3)), + "test 3" + ) + // (-2/4 - 6/9 x - 4/9 x^2) + (2/4 + 6/9 x + 4/9 x^2) ?= 0 + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0)), + Polynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)) + + Polynomial(Rational(2, 4), Rational(6, 9), Rational(4, 9)), + "test 4" + ) + } + } + @Test + fun test_Polynomial_Polynomial_minus() { + RationalField.polynomialSpace { + // (5/9 - 8/9 x - 8/7 x^2) - (-5/7 + 5/1 x + 5/8 x^2) ?= 80/63 - 53/9 x - 99/56 x^2 + assertEquals( + Polynomial(Rational(80, 63), Rational(-53, 9), Rational(-99, 56)), + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - + Polynomial(Rational(-5, 7), Rational(5, 1), Rational(5, 8)), + "test 1" + ) + // (-2/9 - 8/3 x) - (0 + 9/4 x + 2/4 x^2) ?= -2/9 - 59/12 x - 2/4 x^2 + assertEquals( + Polynomial(Rational(-2, 9), Rational(-59, 12), Rational(-2, 4)), + Polynomial(Rational(-2, 9), Rational(-8, 3)) - + Polynomial(Rational(0), Rational(9, 4), Rational(2, 4)), + "test 2" + ) + // (-4/7 - 2/6 x + 0 x^2 + 0 x^3) - (-6/3 - 7/2 x + 2/3 x^2) ?= 10/7 + 19/6 x - 2/3 x^2 + assertEquals( + Polynomial(Rational(10, 7), Rational(19, 6), Rational(-2, 3), Rational(0)), + Polynomial(Rational(-4, 7), Rational(-2, 6), Rational(0), Rational(0)) - + Polynomial(Rational(-6, 3), Rational(-7, 2), Rational(2, 3)), + "test 3" + ) + // (-2/4 - 6/9 x - 4/9 x^2) - (-2/4 - 6/9 x - 4/9 x^2) ?= 0 + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0)), + Polynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)) - + Polynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)), + "test 4" + ) + } + } + @Test + fun test_Polynomial_Polynomial_times() { + IntModuloRing(35).polynomialSpace { + // (1 + x + x^2) * (1 - x + x^2) ?= 1 + x^2 + x^4 + assertEquals( + Polynomial(1, 0, 1, 0, 1), + Polynomial(1, -1, 1) * Polynomial(1, 1, 1), + "test 1" + ) + // Spoiler: 5 * 7 = 0 + assertEquals( + Polynomial(0, 0, 0, 0, 0), + Polynomial(5, -25, 10) * Polynomial(21, 14, -7), + "test 2" + ) + } + } +} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt new file mode 100644 index 000000000..820b487b4 --- /dev/null +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt @@ -0,0 +1,134 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import space.kscience.kmath.functions.testUtils.Rational +import space.kscience.kmath.functions.testUtils.RationalField +import space.kscience.kmath.misc.UnstableKMathAPI +import kotlin.test.Test +import kotlin.test.assertEquals + + +@OptIn(UnstableKMathAPI::class) +class PolynomialUtilTest { + @Test + fun test_Polynomial_substitute_Double() { + assertEquals( + 0.0, + Polynomial(1.0, -2.0, 1.0).substitute(1.0), + 0.001, + "test 1" + ) + assertEquals( + 0.0, + Polynomial(1.0, -2.0, 1.0).substitute(1.0), + 0.001, + "test 1" + ) + assertEquals( + 1.1931904761904761, + Polynomial(0.625, 2.6666666666666665, 0.5714285714285714, 1.5).substitute(0.2), + 0.001, + "test 2" + ) + assertEquals( + 0.5681904761904762, + Polynomial(0.0, 2.6666666666666665, 0.5714285714285714, 1.5).substitute(0.2), + 0.001, + "test 3" + ) + assertEquals( + 1.1811904761904761, + Polynomial(0.625, 2.6666666666666665, 0.5714285714285714, 0.0).substitute(0.2), + 0.001, + "test 4" + ) + assertEquals( + 1.1703333333333332, + Polynomial(0.625, 2.6666666666666665, 0.0, 1.5).substitute(0.2), + 0.001, + "test 5" + ) + } + @Test + fun test_Polynomial_substitute_Constant() { + assertEquals( + Rational(0), + Polynomial(Rational(1), Rational(-2), Rational(1)).substitute(RationalField, Rational(1)), + "test 1" + ) + assertEquals( + Rational(25057, 21000), + Polynomial(Rational(5, 8), Rational(8, 3), Rational(4, 7), Rational(3, 2)) + .substitute(RationalField, Rational(1, 5)), + "test 2" + ) + assertEquals( + Rational(2983, 5250), + Polynomial(Rational(0), Rational(8, 3), Rational(4, 7), Rational(3, 2)) + .substitute(RationalField, Rational(1, 5)), + "test 3" + ) + assertEquals( + Rational(4961, 4200), + Polynomial(Rational(5, 8), Rational(8, 3), Rational(4, 7), Rational(0)) + .substitute(RationalField, Rational(1, 5)), + "test 4" + ) + assertEquals( + Rational(3511, 3000), + Polynomial(Rational(5, 8), Rational(8, 3), Rational(0), Rational(3, 2)) + .substitute(RationalField, Rational(1, 5)), + "test 5" + ) + } + @Test + fun test_Polynomial_derivative() { + assertEquals( + Polynomial(Rational(-2), Rational(2)), + Polynomial(Rational(1), Rational(-2), Rational(1)).derivative(RationalField), + "test 1" + ) + assertEquals( + Polynomial(Rational(-8, 3), Rational(8, 9), Rational(15, 7), Rational(-20, 9)), + Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).derivative(RationalField), + "test 2" + ) + assertEquals( + Polynomial(Rational(0), Rational(8, 9), Rational(15, 7), Rational(-20, 9)), + Polynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).derivative(RationalField), + "test 3" + ) + assertEquals( + Polynomial(Rational(-8, 3), Rational(8, 9), Rational(15, 7), Rational(0)), + Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).derivative(RationalField), + "test 4" + ) + } + @Test + fun test_Polynomial_antiderivative() { + assertEquals( + Polynomial(Rational(0), Rational(1), Rational(-1), Rational(1, 3)), + Polynomial(Rational(1), Rational(-2), Rational(1)).antiderivative(RationalField), + "test 1" + ) + assertEquals( + Polynomial(Rational(0), Rational(1, 5), Rational(-4, 3), Rational(4, 27), Rational(5, 28), Rational(-1, 9)), + Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).antiderivative(RationalField), + "test 2" + ) + assertEquals( + Polynomial(Rational(0), Rational(0), Rational(0), Rational(4, 27), Rational(5, 28), Rational(-1, 9)), + Polynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).antiderivative(RationalField), + "test 3" + ) + assertEquals( + Polynomial(Rational(0), Rational(1, 5), Rational(-4, 3), Rational(4, 27), Rational(5, 28), Rational(0)), + Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).antiderivative(RationalField), + "test 4" + ) + } +} \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt index aae0ad017..afeba0be4 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.integration -import space.kscience.kmath.functions.ListPolynomial +import space.kscience.kmath.functions.Polynomial import space.kscience.kmath.functions.integrate import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField @@ -19,7 +19,7 @@ class SplineIntegralTest { @Test fun integratePolynomial(){ - val polynomial = ListPolynomial(1.0, 2.0, 3.0) + val polynomial = Polynomial(1.0, 2.0, 3.0) val integral = polynomial.integrate(DoubleField,1.0..2.0) assertEquals(11.0, integral, 0.001) } 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 index 88ee1cbb8..6243818b4 100644 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt @@ -6,6 +6,7 @@ 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 diff --git a/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt b/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt index 997a966a7..e534c243e 100644 --- a/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt +++ b/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt @@ -6,13 +6,13 @@ package space.kscience.kmath.functions.testUtils import space.kscience.kmath.functions.Polynomial -import space.kscience.kmath.functions.ListPolynomialSpace +import space.kscience.kmath.functions.PolynomialSpace -public fun ListPolynomialSpace.ListPolynomial(vararg coefs: Int): Polynomial = +public fun PolynomialSpace.Polynomial(vararg coefs: Int): Polynomial = Polynomial(coefs.map { IntModulo(it, ring.modulus) }) -public fun IntModuloRing.ListPolynomial(vararg coefs: Int): Polynomial = +public fun IntModuloRing.Polynomial(vararg coefs: Int): Polynomial = Polynomial(coefs.map { IntModulo(it, modulus) }) public fun IntModuloRing.m(arg: Int): IntModulo = IntModulo(arg, modulus) -public fun ListPolynomialSpace.m(arg: Int): IntModulo = IntModulo(arg, ring.modulus) \ No newline at end of file +public fun PolynomialSpace.m(arg: Int): IntModulo = IntModulo(arg, ring.modulus) \ No newline at end of file diff --git a/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt b/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt new file mode 100644 index 000000000..933c4dc4c --- /dev/null +++ b/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt @@ -0,0 +1,133 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +@file:Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress") + +package space.kscience.kmath.functions.testUtils + +import space.kscience.kmath.operations.Ring + + +public class IntModulo { + public val residue: Int + public 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 + } + } + + public constructor(residue: Int, modulus: Int) : this(residue, modulus, true) + + public operator fun unaryPlus(): IntModulo = this + public operator fun unaryMinus(): IntModulo = + IntModulo( + if (residue == 0) 0 else modulus - residue, + modulus, + toCheckInput = false + ) + public 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 + ) + } + public operator fun plus(other: Int): IntModulo = + IntModulo( + (residue + other) % modulus, + modulus, + toCheckInput = false + ) + public 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 + ) + } + public operator fun minus(other: Int): IntModulo = + IntModulo( + (residue - other) % modulus, + modulus, + toCheckInput = false + ) + public 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 + ) + } + public operator fun times(other: Int): IntModulo = + IntModulo( + (residue * other) % modulus, + modulus, + toCheckInput = false + ) + public 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 + ) + } + public 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") +public class IntModuloRing : Ring { + + public val modulus: Int + + public 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) + + public 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 + public inline fun IntModulo.div(arg: IntModulo): IntModulo = this / arg +} \ No newline at end of file diff --git a/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt b/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt new file mode 100644 index 000000000..32ca1c3aa --- /dev/null +++ b/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions.testUtils + +import space.kscience.kmath.functions.ListPolynomial +import space.kscience.kmath.functions.Polynomial +import space.kscience.kmath.functions.ListPolynomialSpace +import space.kscience.kmath.functions.PolynomialSpaceOverRing + + +public fun ListPolynomialSpace.ListPolynomial(vararg coefs: Int): ListPolynomial = + ListPolynomial(coefs.map { IntModulo(it, ring.modulus) }) +public fun IntModuloRing.ListPolynomial(vararg coefs: Int): ListPolynomial = + ListPolynomial(coefs.map { IntModulo(it, modulus) }) + +public fun IntModuloRing.m(arg: Int): IntModulo = IntModulo(arg, modulus) +public fun PolynomialSpaceOverRing.m(arg: Int): IntModulo = IntModulo(arg, ring.modulus) \ No newline at end of file diff --git a/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/NTMisc.kt b/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/NTMisc.kt new file mode 100644 index 000000000..ff67f19d8 --- /dev/null +++ b/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/NTMisc.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.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/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt b/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt new file mode 100644 index 000000000..27b0eb21e --- /dev/null +++ b/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt @@ -0,0 +1,177 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +@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") +public class Rational { + public companion object { + public val ZERO: Rational = Rational(0L) + public val ONE: Rational = Rational(1L) + } + + public val numerator: Long + public 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 + } + } + + public constructor(numerator: Int, denominator: Int) : this(numerator.toLong(), denominator.toLong(), true) + public constructor(numerator: Int, denominator: Long) : this(numerator.toLong(), denominator, true) + public constructor(numerator: Long, denominator: Int) : this(numerator, denominator.toLong(), true) + public constructor(numerator: Long, denominator: Long) : this(numerator, denominator, true) + public constructor(numerator: Int) : this(numerator.toLong(), 1L, false) + public constructor(numerator: Long) : this(numerator, 1L, false) + + public operator fun unaryPlus(): Rational = this + public operator fun unaryMinus(): Rational = Rational(-this.numerator, this.denominator) + public 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 + ) + } + public operator fun plus(other: Int): Rational = + Rational( + numerator + denominator * other.toLong(), + denominator, + toCheckInput = false + ) + public operator fun plus(other: Long): Rational = + Rational( + numerator + denominator * other, + denominator, + toCheckInput = false + ) + public 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 + ) + } + public operator fun minus(other: Int): Rational = + Rational( + numerator - denominator * other.toLong(), + denominator, + toCheckInput = false + ) + public operator fun minus(other: Long): Rational = + Rational( + numerator - denominator * other, + denominator, + toCheckInput = false + ) + public 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 + ) + } + public operator fun times(other: Int): Rational { + val other = other.toLong() + val denominatorAndOtherGcd = gcd(denominator, other) + return Rational( + numerator * (other / denominatorAndOtherGcd), + denominator / denominatorAndOtherGcd, + toCheckInput = false + ) + } + public operator fun times(other: Long): Rational { + val denominatorAndOtherGcd = gcd(denominator, other) + return Rational( + numerator * (other / denominatorAndOtherGcd), + denominator / denominatorAndOtherGcd, + toCheckInput = false + ) + } + public 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) + ) + } + public operator fun div(other: Int): Rational { + val other = other.toLong() + val numeratorAndOtherGcd = gcd(numerator, other) + return Rational( + numerator / numeratorAndOtherGcd, + denominator * (other / numeratorAndOtherGcd), + toCheckInput = false + ) + } + public 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) +public 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/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt b/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt index 9ca5f43a3..5d0b77aa8 100644 --- a/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt +++ b/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt @@ -91,7 +91,6 @@ public fun assertEquals( ) } -// FIXME: Don't understand why but the same function from test-utils-functions module can not be used public inline fun assertFailsWithTypeAndMessage( expectedMessage: String? = null, assertionMessage: String? = null, -- 2.34.1 From 5bc627f1d414730c2b2383a179edf290f6e5a47f Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 12 Jul 2022 01:56:34 +0300 Subject: [PATCH 126/275] Rollback all breaking changes. The only breaking change now is value class. --- .../kscience/kmath/functions/Piecewise.kt | 8 ++-- .../kscience/kmath/functions/Polynomial.kt | 24 +++------- .../kmath/functions/polynomialUtil.kt | 32 ++++--------- .../kmath/integration/SplineIntegrator.kt | 3 +- .../kmath/interpolation/Interpolator.kt | 4 +- .../kmath/functions/PolynomialUtilTest.kt | 46 +++++++++---------- 6 files changed, 45 insertions(+), 72 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt index cfd21d552..16af7f555 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt @@ -117,16 +117,16 @@ public fun > PiecewisePolynomial( * Return a value of polynomial function with given [ring] a given [arg] or null if argument is outside piecewise * definition. */ -public fun , C : Ring> PiecewisePolynomial.substitute(ring: C, arg: T): T? = - findPiece(arg)?.substitute(ring, arg) +public fun , C : Ring> PiecewisePolynomial.value(ring: C, arg: T): T? = + findPiece(arg)?.value(ring, arg) /** * Convert this polynomial to a function returning nullable value (null if argument is outside piecewise range). */ -public fun , C : Ring> PiecewisePolynomial.asFunction(ring: C): (T) -> T? = { substitute(ring, it) } +public fun , C : Ring> PiecewisePolynomial.asFunction(ring: C): (T) -> T? = { value(ring, it) } /** * Convert this polynomial to a function using [defaultValue] for arguments outside the piecewise range. */ public fun , C : Ring> PiecewisePolynomial.asFunction(ring: C, defaultValue: T): (T) -> T = - { substitute(ring, it) ?: defaultValue } + { value(ring, it) ?: defaultValue } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 061f556f6..bfb378cce 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -59,12 +59,12 @@ public value class Polynomial( * @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 PolynomialSpace>( +public open class PolynomialSpace( /** * Underlying ring of constants. Its operations on constants are inherited by local operations on constants. */ public val ring: A, -) : Ring> { +) : Ring>, ScaleOperations> where A : Ring, A : ScaleOperations { /** * Instance of zero constant (zero of the underlying ring). @@ -267,13 +267,15 @@ public open class PolynomialSpace>( override fun add(left: Polynomial, right: Polynomial): Polynomial = left + right override fun multiply(left: Polynomial, right: Polynomial): Polynomial = left * right + override fun scale(a: Polynomial, value: Double): Polynomial = + ring { Polynomial(a.coefficients.map { scale(it, value) }) } // TODO: When context receivers will be ready move all of this substitutions and invocations to utilities with // [ListPolynomialSpace] as a context receiver /** * Evaluates value of [this] polynomial on provided [argument]. */ - public inline fun Polynomial.substitute(argument: C): C = substitute(ring, argument) + public inline fun Polynomial.substitute(argument: C): C = value(ring, argument) /** * Represent [this] polynomial as a regular context-less function. @@ -283,19 +285,5 @@ public open class PolynomialSpace>( /** * Evaluates value of [this] polynomial on provided [argument]. */ - public inline operator fun Polynomial.invoke(argument: C): C = 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 ScalablePolynomialSpace( - ring: A, -) : PolynomialSpace(ring), ScaleOperations> where A : Ring, A : ScaleOperations { - override fun scale(a: Polynomial, value: Double): Polynomial = - ring { Polynomial(a.coefficients.map { scale(it, value) }) } + public inline operator fun Polynomial.invoke(argument: C): C = value(ring, argument) } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt index 0e1259bee..f745bf6e4 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt @@ -16,36 +16,22 @@ import kotlin.math.pow /** * Creates a [PolynomialSpace] over a received ring. */ -public inline val > A.polynomialSpace: PolynomialSpace +public inline val A.polynomialSpace: PolynomialSpace where A : Ring, A : ScaleOperations get() = PolynomialSpace(this) /** * Creates a [PolynomialSpace]'s scope over a received ring. */ // TODO: When context will be ready move [ListPolynomialSpace] and add [A] to context receivers of [block] -public inline fun , R> A.polynomialSpace(block: PolynomialSpace.() -> R): R { +public inline fun A.polynomialSpace(block: PolynomialSpace.() -> R): R where A : Ring, A : ScaleOperations { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return PolynomialSpace(this).block() } -/** - * Creates a [ScalablePolynomialSpace] over a received scalable ring. - */ -public inline val A.scalablePolynomialSpace: ScalablePolynomialSpace where A : Ring, A : ScaleOperations - get() = ScalablePolynomialSpace(this) - -/** - * Creates a [ScalablePolynomialSpace]'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.scalablePolynomialSpace(block: ScalablePolynomialSpace.() -> R): R where A : Ring, A : ScaleOperations { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return ScalablePolynomialSpace(this).block() -} - /** * Evaluates value of [this] Double polynomial on provided Double argument. */ -public fun Polynomial.substitute(arg: Double): Double = +public fun Polynomial.value(arg: Double): Double = coefficients.reduceIndexedOrNull { index, acc, c -> acc + c * arg.pow(index) } ?: .0 @@ -55,7 +41,7 @@ public fun Polynomial.substitute(arg: Double): Double = * * It is an implementation of [Horner's method](https://en.wikipedia.org/wiki/Horner%27s_method). */ -public fun Polynomial.substitute(ring: Ring, arg: C): C = ring { +public fun Polynomial.value(ring: Ring, arg: C): C = ring { if (coefficients.isEmpty()) return zero var result: C = coefficients.last() for (j in coefficients.size - 2 downTo 0) { @@ -67,13 +53,13 @@ public fun Polynomial.substitute(ring: Ring, arg: C): C = ring { /** * Represent [this] polynomial as a regular context-less function. */ -public fun > Polynomial.asFunctionOver(ring: A): (C) -> C = { substitute(ring, it) } +public fun > Polynomial.asFunctionOver(ring: A): (C) -> C = { value(ring, it) } /** * Returns algebraic derivative of received polynomial. */ @UnstableKMathAPI -public fun Polynomial.derivative( +public fun Polynomial.differentiate( ring: A, ): Polynomial where A : Ring, A : NumericAlgebra = ring { Polynomial( @@ -87,7 +73,7 @@ public fun Polynomial.derivative( * Returns algebraic antiderivative of received polynomial. */ @UnstableKMathAPI -public fun Polynomial.antiderivative( +public fun Polynomial.integrate( ring: A, ): Polynomial where A : Field, A : NumericAlgebra = ring { Polynomial( @@ -106,6 +92,6 @@ public fun > Polynomial.integrate( ring: Field, range: ClosedRange, ): C { - val antiderivative = antiderivative(ring) - return ring { antiderivative.substitute(ring, range.endInclusive) - antiderivative.substitute(ring, range.start) } + val antiderivative = integrate(ring) + return ring { antiderivative.value(ring, range.endInclusive) - antiderivative.value(ring, range.start) } } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt index 0fcd4c6e5..eb88d9ae0 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 @@ -7,7 +7,6 @@ package space.kscience.kmath.integration import space.kscience.kmath.functions.PiecewisePolynomial import space.kscience.kmath.functions.integrate -import space.kscience.kmath.functions.antiderivative import space.kscience.kmath.interpolation.PolynomialInterpolator import space.kscience.kmath.interpolation.SplineInterpolator import space.kscience.kmath.interpolation.interpolatePolynomials @@ -24,7 +23,7 @@ import space.kscience.kmath.structures.MutableBufferFactory @OptIn(PerformancePitfall::class) @UnstableKMathAPI public fun > PiecewisePolynomial.integrate(algebra: Field): PiecewisePolynomial = - PiecewisePolynomial(pieces.map { it.first to it.second.antiderivative(algebra) }) + PiecewisePolynomial(pieces.map { it.first to it.second.integrate(algebra) }) /** * Compute definite integral of given [PiecewisePolynomial] piece by piece in a given [range] diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt index 62819be0c..2266092a3 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt @@ -10,7 +10,7 @@ package space.kscience.kmath.interpolation import space.kscience.kmath.data.XYColumnarData import space.kscience.kmath.functions.PiecewisePolynomial import space.kscience.kmath.functions.asFunction -import space.kscience.kmath.functions.substitute +import space.kscience.kmath.functions.value import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Ring import space.kscience.kmath.structures.Buffer @@ -34,7 +34,7 @@ public interface PolynomialInterpolator> : Interpolator): PiecewisePolynomial override fun interpolate(points: XYColumnarData): (T) -> T = { x -> - interpolatePolynomials(points).substitute(algebra, x) ?: getDefaultValue() + interpolatePolynomials(points).value(algebra, x) ?: getDefaultValue() } } diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt index 820b487b4..9d0fe4cc3 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt @@ -15,119 +15,119 @@ import kotlin.test.assertEquals @OptIn(UnstableKMathAPI::class) class PolynomialUtilTest { @Test - fun test_Polynomial_substitute_Double() { + fun test_Polynomial_value_Double() { assertEquals( 0.0, - Polynomial(1.0, -2.0, 1.0).substitute(1.0), + Polynomial(1.0, -2.0, 1.0).value(1.0), 0.001, "test 1" ) assertEquals( 0.0, - Polynomial(1.0, -2.0, 1.0).substitute(1.0), + Polynomial(1.0, -2.0, 1.0).value(1.0), 0.001, "test 1" ) assertEquals( 1.1931904761904761, - Polynomial(0.625, 2.6666666666666665, 0.5714285714285714, 1.5).substitute(0.2), + Polynomial(0.625, 2.6666666666666665, 0.5714285714285714, 1.5).value(0.2), 0.001, "test 2" ) assertEquals( 0.5681904761904762, - Polynomial(0.0, 2.6666666666666665, 0.5714285714285714, 1.5).substitute(0.2), + Polynomial(0.0, 2.6666666666666665, 0.5714285714285714, 1.5).value(0.2), 0.001, "test 3" ) assertEquals( 1.1811904761904761, - Polynomial(0.625, 2.6666666666666665, 0.5714285714285714, 0.0).substitute(0.2), + Polynomial(0.625, 2.6666666666666665, 0.5714285714285714, 0.0).value(0.2), 0.001, "test 4" ) assertEquals( 1.1703333333333332, - Polynomial(0.625, 2.6666666666666665, 0.0, 1.5).substitute(0.2), + Polynomial(0.625, 2.6666666666666665, 0.0, 1.5).value(0.2), 0.001, "test 5" ) } @Test - fun test_Polynomial_substitute_Constant() { + fun test_Polynomial_value_Constant() { assertEquals( Rational(0), - Polynomial(Rational(1), Rational(-2), Rational(1)).substitute(RationalField, Rational(1)), + Polynomial(Rational(1), Rational(-2), Rational(1)).value(RationalField, Rational(1)), "test 1" ) assertEquals( Rational(25057, 21000), Polynomial(Rational(5, 8), Rational(8, 3), Rational(4, 7), Rational(3, 2)) - .substitute(RationalField, Rational(1, 5)), + .value(RationalField, Rational(1, 5)), "test 2" ) assertEquals( Rational(2983, 5250), Polynomial(Rational(0), Rational(8, 3), Rational(4, 7), Rational(3, 2)) - .substitute(RationalField, Rational(1, 5)), + .value(RationalField, Rational(1, 5)), "test 3" ) assertEquals( Rational(4961, 4200), Polynomial(Rational(5, 8), Rational(8, 3), Rational(4, 7), Rational(0)) - .substitute(RationalField, Rational(1, 5)), + .value(RationalField, Rational(1, 5)), "test 4" ) assertEquals( Rational(3511, 3000), Polynomial(Rational(5, 8), Rational(8, 3), Rational(0), Rational(3, 2)) - .substitute(RationalField, Rational(1, 5)), + .value(RationalField, Rational(1, 5)), "test 5" ) } @Test - fun test_Polynomial_derivative() { + fun test_Polynomial_differentiate() { assertEquals( Polynomial(Rational(-2), Rational(2)), - Polynomial(Rational(1), Rational(-2), Rational(1)).derivative(RationalField), + Polynomial(Rational(1), Rational(-2), Rational(1)).differentiate(RationalField), "test 1" ) assertEquals( Polynomial(Rational(-8, 3), Rational(8, 9), Rational(15, 7), Rational(-20, 9)), - Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).derivative(RationalField), + Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).differentiate(RationalField), "test 2" ) assertEquals( Polynomial(Rational(0), Rational(8, 9), Rational(15, 7), Rational(-20, 9)), - Polynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).derivative(RationalField), + Polynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).differentiate(RationalField), "test 3" ) assertEquals( Polynomial(Rational(-8, 3), Rational(8, 9), Rational(15, 7), Rational(0)), - Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).derivative(RationalField), + Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).differentiate(RationalField), "test 4" ) } @Test - fun test_Polynomial_antiderivative() { + fun test_Polynomial_integrate() { assertEquals( Polynomial(Rational(0), Rational(1), Rational(-1), Rational(1, 3)), - Polynomial(Rational(1), Rational(-2), Rational(1)).antiderivative(RationalField), + Polynomial(Rational(1), Rational(-2), Rational(1)).integrate(RationalField), "test 1" ) assertEquals( Polynomial(Rational(0), Rational(1, 5), Rational(-4, 3), Rational(4, 27), Rational(5, 28), Rational(-1, 9)), - Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).antiderivative(RationalField), + Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).integrate(RationalField), "test 2" ) assertEquals( Polynomial(Rational(0), Rational(0), Rational(0), Rational(4, 27), Rational(5, 28), Rational(-1, 9)), - Polynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).antiderivative(RationalField), + Polynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).integrate(RationalField), "test 3" ) assertEquals( Polynomial(Rational(0), Rational(1, 5), Rational(-4, 3), Rational(4, 27), Rational(5, 28), Rational(0)), - Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).antiderivative(RationalField), + Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).integrate(RationalField), "test 4" ) } -- 2.34.1 From f7d159bc036d2fa2496906e612db67fa6ce42e06 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 12 Jul 2022 02:05:29 +0300 Subject: [PATCH 127/275] Made IntModulo implement ScaleOperations. --- .../space/kscience/kmath/functions/testUtils/IntModulo.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt b/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt index 933c4dc4c..21095d858 100644 --- a/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt +++ b/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt @@ -8,6 +8,7 @@ package space.kscience.kmath.functions.testUtils import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.ScaleOperations public class IntModulo { @@ -108,7 +109,7 @@ public class IntModulo { } @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE") -public class IntModuloRing : Ring { +public class IntModuloRing : Ring, ScaleOperations { public val modulus: Int @@ -130,4 +131,6 @@ public class IntModuloRing : Ring { override inline fun IntModulo.minus(arg: IntModulo): IntModulo = this - arg override inline fun IntModulo.times(arg: IntModulo): IntModulo = this * arg public inline fun IntModulo.div(arg: IntModulo): IntModulo = this / arg + + override fun scale(a: IntModulo, value: Double): IntModulo = a * value.toInt() } \ No newline at end of file -- 2.34.1 From 0eb9bd810c26fffff4f4542cf256f643a6279cc2 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 12 Jul 2022 22:56:08 +0300 Subject: [PATCH 128/275] Kotlin 1.7.10 --- .space.kts | 2 +- gradle.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.space.kts b/.space.kts index d70ad6d59..c9500e967 100644 --- a/.space.kts +++ b/.space.kts @@ -1,3 +1,3 @@ job("Build") { gradlew("openjdk:11", "build") -} +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 5202289fa..6b45ee49f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,4 +12,4 @@ org.gradle.configureondemand=true org.gradle.parallel=true org.gradle.jvmargs=-Xmx4096m -toolsVersion=0.11.7-kotlin-1.7.0 +toolsVersion=0.11.8-kotlin-1.7.10 -- 2.34.1 From 87aeda84d9fcbbed2a250695010fb7f254acb276 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 12 Jul 2022 23:10:38 +0300 Subject: [PATCH 129/275] Added MathJax to docs. --- kmath-functions/build.gradle.kts | 4 ++++ .../space/kscience/kmath/functions/Polynomial.kt | 10 +++++++--- kmath-polynomial/build.gradle.kts | 4 ++++ .../LabeledPolynomial.kt | 13 +++++++++---- .../ListPolynomial.kt | 9 ++++++--- .../NumberedPolynomial.kt | 13 +++++++------ .../labeledConstructors.kt | 14 +++++++++----- .../numberedConstructors.kt | 12 ++++++++---- 8 files changed, 54 insertions(+), 25 deletions(-) diff --git a/kmath-functions/build.gradle.kts b/kmath-functions/build.gradle.kts index 0a8e8a1be..149a8f277 100644 --- a/kmath-functions/build.gradle.kts +++ b/kmath-functions/build.gradle.kts @@ -19,6 +19,10 @@ kotlin.sourceSets { } } +dependencies { + dokkaPlugin("org.jetbrains.dokka:mathjax-plugin:${versionCatalogs.named("npmlibs").findVersion("dokka").get().requiredVersion}") +} + readme { maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index bfb378cce..1e811d3ba 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -23,8 +23,10 @@ import kotlin.math.min @JvmInline public value class Polynomial( /** - * List that contains coefficients of the polynomial. Every monomial `a x^d` is stored as a coefficient `a` placed - * into the list at index `d`. For example, coefficients of a polynomial `5 x^2 - 6` can be represented as + * 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 + @@ -42,9 +44,11 @@ public value class Polynomial( * 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 + * 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 ) { diff --git a/kmath-polynomial/build.gradle.kts b/kmath-polynomial/build.gradle.kts index dcfcb1b46..b0f4a095c 100644 --- a/kmath-polynomial/build.gradle.kts +++ b/kmath-polynomial/build.gradle.kts @@ -20,6 +20,10 @@ kotlin.sourceSets { } } +dependencies { + dokkaPlugin("org.jetbrains.dokka:mathjax-plugin:${versionCatalogs.named("npmlibs").findVersion("dokka").get().requiredVersion}") +} + readme { maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) 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 index 7f107a87f..12bf9f839 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/LabeledPolynomial.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/LabeledPolynomial.kt @@ -25,9 +25,9 @@ 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 + * 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( @@ -55,7 +55,12 @@ internal constructor( * ) to 0 * ) * ``` - * where `a`, `b` and `c` are corresponding [Symbol] objects. + * 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> ) : Polynomial { 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 index 76e1a6bb6..91b9c7658 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/ListPolynomial.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/ListPolynomial.kt @@ -21,8 +21,10 @@ import kotlin.math.min */ 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 + * 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 + @@ -40,9 +42,10 @@ public data class ListPolynomial( * 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 + * 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 ) : Polynomial { 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 index f7dd9d8de..96c96e555 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/NumberedPolynomial.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/NumberedPolynomial.kt @@ -24,9 +24,9 @@ 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 + * 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 + @@ -41,9 +41,10 @@ internal constructor( * 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 + * 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> ) : Polynomial { @@ -325,7 +326,7 @@ public class NumberedPolynomialSpace>( /** * Maximal index (ID) of variable occurring in the polynomial with positive power. If there is no such variable, - * the result is `-1`. + * the result is -1. */ public val NumberedPolynomial.lastVariable: Int get() = coefficients.keys.maxOfOrNull { degs -> degs.lastIndex } ?: -1 @@ -365,7 +366,7 @@ public class NumberedPolynomialSpace>( } ?: 0u /** * Count of variables occurring in the polynomial with positive power. If there is no such variable, - * the result is `0`. + * the result is 0. */ public val NumberedPolynomial.countOfVariables: Int get() = 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 index 819a36449..d23efc5c2 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/labeledConstructors.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/labeledConstructors.kt @@ -262,7 +262,7 @@ public inline fun C.asLabeledPolynomial() : LabeledPolynomial = LabeledPo /** * 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 + * For example, polynomial \(5 a^2 c^3 - 6 b\) can be described as * ``` * Int.algebra { * val numberedPolynomial : NumberedPolynomial = NumberedPolynomial { @@ -271,6 +271,7 @@ public inline fun C.asLabeledPolynomial() : LabeledPolynomial = LabeledPo * } * } * ``` + * @usesMathJax */ @DslMarker @UnstableKMathAPI @@ -385,7 +386,7 @@ public class DSL1LabeledPolynomialBuilder( ///** // * Creates [LabeledPolynomial] with lambda [block] in context of [this] ring of constants. // * -// * For example, polynomial `5 x_1^2 x_3^3 - 6 x_2` can be described as +// * For example, polynomial \(5 x_1^2 x_3^3 - 6 x_2\) can be described as // * ``` // * Int.algebra { // * val LabeledPolynomial : LabeledPolynomial = LabeledPolynomial { @@ -394,6 +395,7 @@ public class DSL1LabeledPolynomialBuilder( // * } // * } // * ``` +// * @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. @@ -404,7 +406,7 @@ public class DSL1LabeledPolynomialBuilder( /** * Creates [LabeledPolynomial] with lambda [block] in context of [this] ring of [LabeledPolynomial]s. * - * For example, polynomial `5 x_1^2 x_3^3 - 6 x_2` can be described as + * For example, polynomial \(5 x_1^2 x_3^3 - 6 x_2\) can be described as * ``` * Int.algebra { * val LabeledPolynomial : LabeledPolynomial = LabeledPolynomial { @@ -413,14 +415,15 @@ public class DSL1LabeledPolynomialBuilder( * } * } * ``` + * @usesMathJax */ @UnstableKMathAPI public inline fun > LabeledPolynomialSpace.LabeledPolynomialDSL1(initialCapacity: Int = 0, 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 x_1^2 x_3^3 - 6 x_2` can be described as - * ``` + * For example, polynomial \(5 x_1^2 x_3^3 - 6 x_2\) can be described as + * `` * Int.algebra { * val LabeledPolynomial : LabeledPolynomial = LabeledPolynomial { * 5 { 1 inPowerOf 2u; 3 inPowerOf 3u } // 5 x_1^2 x_3^3 + @@ -428,6 +431,7 @@ public inline fun > LabeledPolynomialSpace.LabeledPolynomial * } * } * ``` + * @usesMathJax */ @UnstableKMathAPI public inline fun > LabeledRationalFunctionSpace.LabeledPolynomialDSL1(initialCapacity: Int = 0, block: DSL1LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = DSL1LabeledPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build() 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 index 8d2c9e617..051019159 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/numberedConstructors.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/numberedConstructors.kt @@ -243,7 +243,7 @@ public inline fun C.asNumberedPolynomial() : NumberedPolynomial = Numbere /** * Marks DSL that allows to more simply create [NumberedPolynomial]s with good performance. * - * For example, polynomial `5 x_1^2 x_3^3 - 6 x_2` can be described as + * For example, polynomial \(5 x_1^2 x_3^3 - 6 x_2\) can be described as * ``` * Int.algebra { * val numberedPolynomial : NumberedPolynomial = NumberedPolynomial { @@ -252,6 +252,7 @@ public inline fun C.asNumberedPolynomial() : NumberedPolynomial = Numbere * } * } * ``` + * @usesMathJax */ @DslMarker @UnstableKMathAPI @@ -372,7 +373,7 @@ public class DSL1NumberedPolynomialBuilder( ///** // * Creates [NumberedPolynomial] with lambda [block] in context of [this] ring of constants. // * -// * For example, polynomial `5 x_1^2 x_3^3 - 6 x_2` can be described as +// * For example, polynomial \(5 x_1^2 x_3^3 - 6 x_2\) can be described as // * ``` // * Int.algebra { // * val numberedPolynomial : NumberedPolynomial = NumberedPolynomial { @@ -381,6 +382,7 @@ public class DSL1NumberedPolynomialBuilder( // * } // * } // * ``` +// * @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. @@ -391,7 +393,7 @@ public class DSL1NumberedPolynomialBuilder( /** * Creates [NumberedPolynomial] with lambda [block] in context of [this] ring of [NumberedPolynomial]s. * - * For example, polynomial `5 x_1^2 x_3^3 - 6 x_2` can be described as + * For example, polynomial \(5 x_1^2 x_3^3 - 6 x_2\) can be described as * ``` * Int.algebra { * val numberedPolynomial : NumberedPolynomial = NumberedPolynomial { @@ -400,13 +402,14 @@ public class DSL1NumberedPolynomialBuilder( * } * } * ``` + * @usesMathJax */ @UnstableKMathAPI public inline fun > NumberedPolynomialSpace.NumberedPolynomialDSL1(initialCapacity: Int = 0, 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_1^2 x_3^3 - 6 x_2` can be described as + * For example, polynomial \(5 x_1^2 x_3^3 - 6 x_2\) can be described as * ``` * Int.algebra { * val numberedPolynomial : NumberedPolynomial = NumberedPolynomial { @@ -415,6 +418,7 @@ public inline fun > NumberedPolynomialSpace.NumberedPolynomi * } * } * ``` + * @usesMathJax */ @UnstableKMathAPI public inline fun > NumberedRationalFunctionSpace.NumberedPolynomialDSL1(initialCapacity: Int = 0, block: DSL1NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = DSL1NumberedPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build() -- 2.34.1 From 4ea29c82c5abcc079123bd964f77ac4ea0e307a8 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Wed, 13 Jul 2022 12:05:53 +0300 Subject: [PATCH 130/275] Small fix of DSL1. --- .../kscience/kmath/functions/polynomials.kt | 4 +- .../labeledConstructors.kt | 40 +++++++++---------- .../numberedConstructors.kt | 36 ++++++++--------- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt index 4151b0283..c65ca589d 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt @@ -107,8 +107,8 @@ fun numberedPolynomialsExample() { // Also there is DSL for constructing NumberedPolynomials: val polynomial5: NumberedPolynomial = NumberedPolynomialDSL1 { 3 {} - 5 { 2 inPowerOf 1u } - -7 with { 1 pow 2u; 3 pow 1u } + 5 { 1 inPowerOf 1u } + -7 with { 0 pow 2u; 2 pow 1u } // `pow` and `inPowerOf` are the same // `with` is omittable } 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 index d23efc5c2..aa44660c1 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/labeledConstructors.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/labeledConstructors.kt @@ -265,7 +265,7 @@ public inline fun C.asLabeledPolynomial() : LabeledPolynomial = LabeledPo * For example, polynomial \(5 a^2 c^3 - 6 b\) can be described as * ``` * Int.algebra { - * val numberedPolynomial : NumberedPolynomial = NumberedPolynomial { + * val labeledPolynomial : LabeledPolynomial = LabeledPolynomialDSL1 { * 5 { a inPowerOf 2u; c inPowerOf 3u } // 5 a^2 c^3 + * (-6) { b inPowerOf 1u } // (-6) b^1 * } @@ -339,18 +339,18 @@ public class DSL1LabeledPolynomialBuilder( /** * Initial capacity of coefficients map. */ - initialCapacity: Int = 0 + 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> = LinkedHashMap(initialCapacity) + 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>`. + * In fact, it just returns [coefficients] as regular coefficients map of type `Map, C>`. */ @PublishedApi internal fun build(): LabeledPolynomial = LabeledPolynomial(coefficients) @@ -386,12 +386,12 @@ public class DSL1LabeledPolynomialBuilder( ///** // * Creates [LabeledPolynomial] with lambda [block] in context of [this] ring of constants. // * -// * For example, polynomial \(5 x_1^2 x_3^3 - 6 x_2\) can be described as +// * For example, polynomial \(5 a^2 c^3 - 6 b\) can be described as // * ``` // * Int.algebra { -// * val LabeledPolynomial : LabeledPolynomial = LabeledPolynomial { -// * 5 { 1 inPowerOf 2u; 3 inPowerOf 3u } // 5 x_1^2 x_3^3 + -// * (-6) { 2 inPowerOf 1u } // (-6) x_2^1 +// * val labeledPolynomial : LabeledPolynomial = LabeledPolynomialDSL1 { +// * 5 { a inPowerOf 2u; c inPowerOf 3u } // 5 a^2 c^3 + +// * (-6) { b inPowerOf 1u } // (-6) b^1 // * } // * } // * ``` @@ -402,39 +402,39 @@ public class DSL1LabeledPolynomialBuilder( // 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 = 0, block: LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = LabeledPolynomialBuilder(::add, initialCapacity).apply(block).build() +//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 x_1^2 x_3^3 - 6 x_2\) can be described as + * For example, polynomial \(5 a^2 c^3 - 6 b\) can be described as * ``` * Int.algebra { - * val LabeledPolynomial : LabeledPolynomial = LabeledPolynomial { - * 5 { 1 inPowerOf 2u; 3 inPowerOf 3u } // 5 x_1^2 x_3^3 + - * (-6) { 2 inPowerOf 1u } // (-6) x_2^1 + * 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 = 0, block: DSL1LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = DSL1LabeledPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build() +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 x_1^2 x_3^3 - 6 x_2\) can be described as - * `` + * For example, polynomial \(5 a^2 c^3 - 6 b\) can be described as + * ``` * Int.algebra { - * val LabeledPolynomial : LabeledPolynomial = LabeledPolynomial { - * 5 { 1 inPowerOf 2u; 3 inPowerOf 3u } // 5 x_1^2 x_3^3 + - * (-6) { 2 inPowerOf 1u } // (-6) x_2^1 + * 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 = 0, block: DSL1LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = DSL1LabeledPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build() +public inline fun > LabeledRationalFunctionSpace.LabeledPolynomialDSL1(initialCapacity: Int? = null, block: DSL1LabeledPolynomialBuilder.() -> Unit) : LabeledPolynomial = DSL1LabeledPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build() // Waiting for context receivers :( FIXME: Replace with context receivers when they will be available 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 index 051019159..ce0db3d17 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/numberedConstructors.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/numberedConstructors.kt @@ -243,12 +243,12 @@ public inline fun C.asNumberedPolynomial() : NumberedPolynomial = Numbere /** * Marks DSL that allows to more simply create [NumberedPolynomial]s with good performance. * - * For example, polynomial \(5 x_1^2 x_3^3 - 6 x_2\) can be described as + * For example, polynomial \(5 x_0^2 x_2^3 - 6 x_1\) can be described as * ``` * Int.algebra { * val numberedPolynomial : NumberedPolynomial = NumberedPolynomial { - * 5 { 1 inPowerOf 2u; 3 inPowerOf 3u } // 5 x_1^2 x_3^3 + - * (-6) { 2 inPowerOf 1u } // (-6) x_2^1 + * 5 { 0 inPowerOf 2u; 2 inPowerOf 3u } // 5 x_0^2 x_2^3 + + * (-6) { 1 inPowerOf 1u } // (-6) x_1^1 * } * } * ``` @@ -285,7 +285,7 @@ public class DSL1NumberedPolynomialTermSignatureBuilder { */ public infix fun Int.inPowerOf(deg: UInt) { if (deg == 0u) return - val index = this - 1 + val index = this if (index > signature.lastIndex) { signature.addAll(List(index - signature.lastIndex - 1) { 0u }) signature.add(deg) @@ -326,13 +326,13 @@ public class DSL1NumberedPolynomialBuilder( /** * Initial capacity of coefficients map. */ - initialCapacity: Int = 0 + 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> = LinkedHashMap(initialCapacity) + private val coefficients: MutableMap, C> = if (initialCapacity != null) LinkedHashMap(initialCapacity) else LinkedHashMap() /** * Builds the resulting coefficients map. @@ -373,12 +373,12 @@ public class DSL1NumberedPolynomialBuilder( ///** // * Creates [NumberedPolynomial] with lambda [block] in context of [this] ring of constants. // * -// * For example, polynomial \(5 x_1^2 x_3^3 - 6 x_2\) can be described as +// * For example, polynomial \(5 x_0^2 x_2^3 - 6 x_1\) can be described as // * ``` // * Int.algebra { // * val numberedPolynomial : NumberedPolynomial = NumberedPolynomial { -// * 5 { 1 inPowerOf 2u; 3 inPowerOf 3u } // 5 x_1^2 x_3^3 + -// * (-6) { 2 inPowerOf 1u } // (-6) x_2^1 +// * 5 { 0 inPowerOf 2u; 2 inPowerOf 3u } // 5 x_0^2 x_2^3 + +// * (-6) { 1 inPowerOf 1u } // (-6) x_1^1 // * } // * } // * ``` @@ -389,39 +389,39 @@ public class DSL1NumberedPolynomialBuilder( // 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 = 0, block: NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilder(::add, initialCapacity).apply(block).build() +//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_1^2 x_3^3 - 6 x_2\) can be described as + * For example, polynomial \(5 x_0^2 x_2^3 - 6 x_1\) can be described as * ``` * Int.algebra { * val numberedPolynomial : NumberedPolynomial = NumberedPolynomial { - * 5 { 1 inPowerOf 2u; 3 inPowerOf 3u } // 5 x_1^2 x_3^3 + - * (-6) { 2 inPowerOf 1u } // (-6) x_2^1 + * 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 = 0, block: DSL1NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = DSL1NumberedPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build() +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_1^2 x_3^3 - 6 x_2\) can be described as + * For example, polynomial \(5 x_0^2 x_2^3 - 6 x_1\) can be described as * ``` * Int.algebra { * val numberedPolynomial : NumberedPolynomial = NumberedPolynomial { - * 5 { 1 inPowerOf 2u; 3 inPowerOf 3u } // 5 x_1^2 x_3^3 + - * (-6) { 2 inPowerOf 1u } // (-6) x_2^1 + * 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 = 0, block: DSL1NumberedPolynomialBuilder.() -> Unit) : NumberedPolynomial = DSL1NumberedPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build() +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 -- 2.34.1 From 5846f42141a210bef8ba873030f9566ebc14c5e9 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 15 Jul 2022 15:21:49 +0300 Subject: [PATCH 131/275] Grand derivative refactoring. Phase 1 --- .../kscience/kmath/expressions/DSCompiler.kt | 90 +- .../kmath/expressions/DerivativeStructure.kt | 191 ++-- .../DerivativeStructureExpression.kt | 327 +++--- .../kscience/kmath/linear/LinearSpace.kt | 2 +- .../space/kscience/kmath/misc/annotations.kt | 2 +- .../space/kscience/kmath/nd/BufferND.kt | 2 +- .../space/kscience/kmath/nd/StructureND.kt | 4 +- .../kmath/operations/DoubleBufferOps.kt | 4 +- .../kmath/operations/bufferOperation.kt | 26 +- .../space/kscience/kmath/structures/Buffer.kt | 8 +- .../space/kscience/kmath/ejml/_generated.kt | 1003 ----------------- .../histogram/UniformHistogramGroupND.kt | 6 +- .../kmath/multik/MultikDoubleAlgebra.kt | 7 + .../space/kscience/kmath/stat/Sampler.kt | 2 +- 14 files changed, 311 insertions(+), 1363 deletions(-) delete mode 100644 kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt 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 bb88ce52c..e0050cf03 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 @@ -5,11 +5,11 @@ 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.max import kotlin.math.min internal fun MutableBuffer.fill(element: T, fromIndex: Int = 0, toIndex: Int = size) { @@ -54,7 +54,7 @@ internal fun MutableBuffer.fill(element: T, fromIndex: Int = 0, toIndex: * @property order Derivation order. * @see DerivativeStructure */ -internal class DSCompiler> internal constructor( +class DSCompiler> internal constructor( val algebra: A, val bufferFactory: MutableBufferFactory, val freeParameters: Int, @@ -120,8 +120,7 @@ internal class DSCompiler> internal constructor( * This number includes the single 0 order derivative element, which is * guaranteed to be stored in the first element of the array. */ - val size: Int - get() = sizes[freeParameters][order] + val size: Int get() = sizes[freeParameters][order] /** * Get the index of a partial derivative in the array. @@ -178,7 +177,7 @@ internal fun DSCompiler.ln( operand: Buffer, operandOffset: Int, result: MutableBuffer, - resultOffset: Int + resultOffset: Int, ) where A : Field, A : ExponentialOperations = algebra { // create the function value and derivatives val function = bufferFactory(1 + order) { zero } @@ -211,7 +210,7 @@ internal fun DSCompiler.pow( operandOffset: Int, n: Int, result: MutableBuffer, - resultOffset: Int + resultOffset: Int, ) where A : Field, A : PowerOperations = algebra { if (n == 0) { // special case, x^0 = 1 for all x @@ -267,7 +266,7 @@ internal fun DSCompiler.exp( operand: Buffer, operandOffset: Int, result: MutableBuffer, - resultOffset: Int + resultOffset: Int, ) where A : Ring, A : ScaleOperations, A : ExponentialOperations = algebra { // create the function value and derivatives val function = bufferFactory(1 + order) { zero } @@ -290,7 +289,7 @@ internal fun DSCompiler.sqrt( operand: Buffer, operandOffset: Int, result: MutableBuffer, - resultOffset: Int + resultOffset: Int, ) where A : Field, A : PowerOperations = algebra { // create the function value and derivatives // [x^(1/n), (1/n)x^((1/n)-1), (1-n)/n^2x^((1/n)-2), ... ] @@ -351,7 +350,7 @@ internal fun DSCompiler.pow( operandOffset: Int, p: Double, result: MutableBuffer, - resultOffset: Int + resultOffset: Int, ) where A : Ring, A : NumericAlgebra, A : PowerOperations, A : ScaleOperations = algebra { // create the function value and derivatives // [x^p, px^(p-1), p(p-1)x^(p-2), ... ] @@ -387,7 +386,7 @@ internal fun DSCompiler.tan( operand: Buffer, operandOffset: Int, result: MutableBuffer, - resultOffset: Int + resultOffset: Int, ) where A : Ring, A : TrigonometricOperations, A : ScaleOperations = algebra { // create the function value and derivatives val function = bufferFactory(1 + order) { zero } @@ -469,7 +468,7 @@ internal fun DSCompiler.sin( operand: Buffer, operandOffset: Int, result: MutableBuffer, - resultOffset: Int + resultOffset: Int, ) where A : Ring, A : ScaleOperations, A : TrigonometricOperations = algebra { // create the function value and derivatives val function = bufferFactory(1 + order) { zero } @@ -497,7 +496,7 @@ internal fun DSCompiler.acos( operand: Buffer, operandOffset: Int, result: MutableBuffer, - resultOffset: Int + resultOffset: Int, ) where A : Field, A : TrigonometricOperations, A : PowerOperations = algebra { // create the function value and derivatives val function = bufferFactory(1 + order) { zero } @@ -559,7 +558,7 @@ internal fun DSCompiler.asin( operand: Buffer, operandOffset: Int, result: MutableBuffer, - resultOffset: Int + resultOffset: Int, ) where A : Field, A : TrigonometricOperations, A : PowerOperations = algebra { // create the function value and derivatives val function = bufferFactory(1 + order) { zero } @@ -618,7 +617,7 @@ internal fun DSCompiler.atan( operand: Buffer, operandOffset: Int, result: MutableBuffer, - resultOffset: Int + resultOffset: Int, ) where A : Field, A : TrigonometricOperations = algebra { // create the function value and derivatives val function = bufferFactory(1 + order) { zero } @@ -678,7 +677,7 @@ internal fun DSCompiler.cosh( operand: Buffer, operandOffset: Int, result: MutableBuffer, - resultOffset: Int + resultOffset: Int, ) where A : Ring, A : ScaleOperations, A : ExponentialOperations = algebra { // create the function value and derivatives val function = bufferFactory(1 + order) { zero } @@ -708,7 +707,7 @@ internal fun DSCompiler.tanh( operand: Buffer, operandOffset: Int, result: MutableBuffer, - resultOffset: Int + resultOffset: Int, ) where A : Field, A : ExponentialOperations = algebra { // create the function value and derivatives val function = bufferFactory(1 + order) { zero } @@ -765,7 +764,7 @@ internal fun DSCompiler.acosh( operand: Buffer, operandOffset: Int, result: MutableBuffer, - resultOffset: Int + resultOffset: Int, ) where A : Field, A : ExponentialOperations, A : PowerOperations = algebra { // create the function value and derivatives val function = bufferFactory(1 + order) { zero } @@ -857,7 +856,7 @@ internal fun DSCompiler.sinh( operand: Buffer, operandOffset: Int, result: MutableBuffer, - resultOffset: Int + resultOffset: Int, ) where A : Field, A : ExponentialOperations = algebra { // create the function value and derivatives val function = bufferFactory(1 + order) { zero } @@ -964,7 +963,7 @@ internal fun DSCompiler.asinh( operand: Buffer, operandOffset: Int, result: MutableBuffer, - resultOffset: Int + resultOffset: Int, ) where A : Field, A : ExponentialOperations, A : PowerOperations = algebra { // create the function value and derivatives val function = bufferFactory(1 + order) { zero } @@ -1109,59 +1108,6 @@ internal fun DSCompiler.atanh( compose(operand, operandOffset, function, result, resultOffset) } -/** - * Get the compiler for number of free parameters and order. - * - * @param parameters number of free parameters. - * @param order derivation order. - * @return cached rules set. - */ -internal fun > getCompiler( - algebra: A, - bufferFactory: MutableBufferFactory, - parameters: Int, - order: Int -): DSCompiler { - // get the cached compilers - val cache: Array?>>? = null - - // we need to create more compilers - val maxParameters: Int = max(parameters, cache?.size ?: 0) - val maxOrder: Int = max(order, if (cache == null) 0 else cache[0].size) - val newCache: Array?>> = Array(maxParameters + 1) { arrayOfNulls(maxOrder + 1) } - - if (cache != null) { - // preserve the already created compilers - for (i in cache.indices) { - cache[i].copyInto(newCache[i], endIndex = cache[i].size) - } - } - - // create the array in increasing diagonal order - - // create the array in increasing diagonal order - for (diag in 0..parameters + order) { - for (o in max(0, diag - parameters)..min(order, diag)) { - val p: Int = diag - o - if (newCache[p][o] == null) { - val valueCompiler: DSCompiler? = if (p == 0) null else newCache[p - 1][o]!! - val derivativeCompiler: DSCompiler? = if (o == 0) null else newCache[p][o - 1]!! - - newCache[p][o] = DSCompiler( - algebra, - bufferFactory, - p, - o, - valueCompiler, - derivativeCompiler, - ) - } - } - } - - return newCache[parameters][order]!! -} - /** * Compile the sizes array. * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DerivativeStructure.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DerivativeStructure.kt index a1a6354f0..01c045cdb 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DerivativeStructure.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DerivativeStructure.kt @@ -6,10 +6,9 @@ package space.kscience.kmath.expressions import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.NumericAlgebra import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.ScaleOperations -import space.kscience.kmath.structures.MutableBuffer +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.asBuffer /** * Class representing both the value and the differentials of a function. @@ -28,128 +27,29 @@ import space.kscience.kmath.structures.MutableBuffer * [Commons Math's `DerivativeStructure`](https://github.com/apache/commons-math/blob/924f6c357465b39beb50e3c916d5eb6662194175/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/analysis/differentiation/DerivativeStructure.java). */ @UnstableKMathAPI -public open class DerivativeStructure internal constructor( - internal val derivativeAlgebra: DerivativeStructureRing, - internal val compiler: DSCompiler, -) where A : Ring, A : NumericAlgebra, A : ScaleOperations { - /** - * Combined array holding all values. - */ - internal var data: MutableBuffer = - derivativeAlgebra.bufferFactory(compiler.size) { derivativeAlgebra.algebra.zero } +public open class DerivativeStructure> @PublishedApi internal constructor( + private val derivativeAlgebra: DerivativeStructureAlgebra, + @PublishedApi internal val data: Buffer, +) { - /** - * Build an instance with all values and derivatives set to 0. - * - * @param parameters number of free parameters. - * @param order derivation order. - */ - public constructor ( - derivativeAlgebra: DerivativeStructureRing, - parameters: Int, - order: Int, - ) : this( - derivativeAlgebra, - getCompiler(derivativeAlgebra.algebra, derivativeAlgebra.bufferFactory, parameters, order), - ) - - /** - * Build an instance representing a constant value. - * - * @param parameters number of free parameters. - * @param order derivation order. - * @param value value of the constant. - * @see DerivativeStructure - */ - public constructor ( - derivativeAlgebra: DerivativeStructureRing, - parameters: Int, - order: Int, - value: T, - ) : this( - derivativeAlgebra, - parameters, - order, - ) { - data[0] = value - } - - /** - * Build an instance representing a variable. - * - * Instances built using this constructor are considered to be the free variables with respect to which - * differentials are computed. As such, their differential with respect to themselves is +1. - * - * @param parameters number of free parameters. - * @param order derivation order. - * @param index index of the variable (from 0 to `parameters - 1`). - * @param value value of the variable. - */ - public constructor ( - derivativeAlgebra: DerivativeStructureRing, - parameters: Int, - order: Int, - index: Int, - value: T, - ) : this(derivativeAlgebra, parameters, order, value) { - require(index < parameters) { "number is too large: $index >= $parameters" } - - if (order > 0) { - // the derivative of the variable with respect to itself is 1. - data[getCompiler(derivativeAlgebra.algebra, derivativeAlgebra.bufferFactory, index, order).size] = - derivativeAlgebra.algebra.one - } - } - - /** - * Build an instance from all its derivatives. - * - * @param parameters number of free parameters. - * @param order derivation order. - * @param derivatives derivatives sorted according to [DSCompiler.getPartialDerivativeIndex]. - */ - public constructor ( - derivativeAlgebra: DerivativeStructureRing, - parameters: Int, - order: Int, - vararg derivatives: T, - ) : this( - derivativeAlgebra, - parameters, - order, - ) { - require(derivatives.size == data.size) { "dimension mismatch: ${derivatives.size} and ${data.size}" } - data = derivativeAlgebra.bufferFactory(data.size) { derivatives[it] } - } - - /** - * Copy constructor. - * - * @param ds instance to copy. - */ - internal constructor(ds: DerivativeStructure) : this(ds.derivativeAlgebra, ds.compiler) { - this.data = ds.data.copy() - } + public val compiler: DSCompiler get() = derivativeAlgebra.compiler /** * The number of free parameters. */ - public val freeParameters: Int - get() = compiler.freeParameters + public val freeParameters: Int get() = compiler.freeParameters /** * The derivation order. */ - public val order: Int - get() = compiler.order + public val order: Int get() = compiler.order /** * The value part of the derivative structure. * * @see getPartialDerivative */ - public val value: T - get() = data[0] + public val value: T get() = data[0] /** * Get a partial derivative. @@ -183,4 +83,75 @@ public open class DerivativeStructure internal constructor( public override fun hashCode(): Int = 227 + 229 * freeParameters + 233 * order + 239 * data.hashCode() + + public companion object { + + /** + * Build an instance representing a variable. + * + * Instances built using this constructor are considered to be the free variables with respect to which + * differentials are computed. As such, their differential with respect to themselves is +1. + */ + public fun > variable( + derivativeAlgebra: DerivativeStructureAlgebra, + index: Int, + value: T, + ): DerivativeStructure { + val compiler = derivativeAlgebra.compiler + require(index < compiler.freeParameters) { "number is too large: $index >= ${compiler.freeParameters}" } + return DerivativeStructure(derivativeAlgebra, derivativeAlgebra.bufferForVariable(index, value)) + } + + /** + * Build an instance from all its derivatives. + * + * @param derivatives derivatives sorted according to [DSCompiler.getPartialDerivativeIndex]. + */ + public fun > ofDerivatives( + derivativeAlgebra: DerivativeStructureAlgebra, + vararg derivatives: T, + ): DerivativeStructure { + val compiler = derivativeAlgebra.compiler + require(derivatives.size == compiler.size) { "dimension mismatch: ${derivatives.size} and ${compiler.size}" } + val data = derivatives.asBuffer() + + return DerivativeStructure( + derivativeAlgebra, + data + ) + } + } +} + +@OptIn(UnstableKMathAPI::class) +private fun > DerivativeStructureAlgebra.bufferForVariable(index: Int, value: T): Buffer { + val buffer = bufferFactory(compiler.size) { algebra.zero } + buffer[0] = value + if (compiler.order > 0) { + // the derivative of the variable with respect to itself is 1. + + val indexOfDerivative = compiler.getPartialDerivativeIndex(*IntArray(numberOfVariables).apply { + set(index, 1) + }) + + buffer[indexOfDerivative] = algebra.one + } + return buffer +} + +/** + * A class implementing both [DerivativeStructure] and [Symbol]. + */ +@UnstableKMathAPI +public class DerivativeStructureSymbol> internal constructor( + derivativeAlgebra: DerivativeStructureAlgebra, + index: Int, + symbol: Symbol, + value: T, +) : Symbol by symbol, DerivativeStructure( + derivativeAlgebra, derivativeAlgebra.bufferForVariable(index, value) +) { + override fun toString(): String = symbol.toString() + override fun equals(other: Any?): Boolean = (other as? Symbol) == symbol + override fun hashCode(): Int = symbol.hashCode() } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpression.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpression.kt index f91fb55e8..638057921 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpression.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpression.kt @@ -7,83 +7,89 @@ package space.kscience.kmath.expressions import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.structures.MutableBufferFactory -import space.kscience.kmath.structures.indices +import kotlin.math.max +import kotlin.math.min -/** - * A class implementing both [DerivativeStructure] and [Symbol]. - */ @UnstableKMathAPI -public class DerivativeStructureSymbol( - derivativeAlgebra: DerivativeStructureRing, - size: Int, - order: Int, - index: Int, - symbol: Symbol, - value: T, -) : Symbol by symbol, DerivativeStructure( - derivativeAlgebra, - size, - order, - index, - value -) where A : Ring, A : NumericAlgebra, A : ScaleOperations { - override fun toString(): String = symbol.toString() - override fun equals(other: Any?): Boolean = (other as? Symbol) == symbol - override fun hashCode(): Int = symbol.hashCode() -} - -/** - * A ring over [DerivativeStructure]. - * - * @property order The derivation order. - * @param bindings The map of bindings values. All bindings are considered free parameters. - */ -@UnstableKMathAPI -public open class DerivativeStructureRing( +public abstract class DerivativeStructureAlgebra>( public val algebra: A, public val bufferFactory: MutableBufferFactory, public val order: Int, bindings: Map, -) : Ring>, ScaleOperations>, - NumericAlgebra>, - ExpressionAlgebra>, - NumbersAddOps> where A : Ring, A : NumericAlgebra, A : ScaleOperations { +) : ExpressionAlgebra> { + public val numberOfVariables: Int = bindings.size - override val zero: DerivativeStructure by lazy { - DerivativeStructure( - this, - numberOfVariables, - order, - ) - } - override val one: DerivativeStructure by lazy { - DerivativeStructure( - this, - numberOfVariables, - order, - algebra.one, - ) - } + /** + * Get the compiler for number of free parameters and order. + * + * @return cached rules set. + */ + @PublishedApi + internal val compiler: DSCompiler by lazy { + // get the cached compilers + val cache: Array?>>? = null - override fun number(value: Number): DerivativeStructure = const(algebra.number(value)) + // we need to create more compilers + val maxParameters: Int = max(numberOfVariables, cache?.size ?: 0) + val maxOrder: Int = max(order, if (cache == null) 0 else cache[0].size) + val newCache: Array?>> = Array(maxParameters + 1) { arrayOfNulls(maxOrder + 1) } + + if (cache != null) { + // preserve the already created compilers + for (i in cache.indices) { + cache[i].copyInto(newCache[i], endIndex = cache[i].size) + } + } + + // create the array in increasing diagonal order + for (diag in 0..numberOfVariables + order) { + for (o in max(0, diag - numberOfVariables)..min(order, diag)) { + val p: Int = diag - o + if (newCache[p][o] == null) { + val valueCompiler: DSCompiler? = if (p == 0) null else newCache[p - 1][o]!! + val derivativeCompiler: DSCompiler? = if (o == 0) null else newCache[p][o - 1]!! + + newCache[p][o] = DSCompiler( + algebra, + bufferFactory, + p, + o, + valueCompiler, + derivativeCompiler, + ) + } + } + } + + return@lazy newCache[numberOfVariables][order]!! + } private val variables: Map> = bindings.entries.mapIndexed { index, (key, value) -> key to DerivativeStructureSymbol( this, - numberOfVariables, - order, index, key, value, ) }.toMap() - public override fun const(value: T): DerivativeStructure = - DerivativeStructure(this, numberOfVariables, order, value) + + + public override fun const(value: T): DerivativeStructure { + val buffer = bufferFactory(compiler.size) { algebra.zero } + buffer[0] = value + + return DerivativeStructure( + this, + buffer + ) + } override fun bindSymbolOrNull(value: String): DerivativeStructureSymbol? = variables[StringSymbol(value)] @@ -103,54 +109,99 @@ public open class DerivativeStructureRing( public fun DerivativeStructure.derivative(vararg symbols: Symbol): T = derivative(symbols.toList()) +} + + +/** + * A ring over [DerivativeStructure]. + * + * @property order The derivation order. + * @param bindings The map of bindings values. All bindings are considered free parameters. + */ +@UnstableKMathAPI +public open class DerivativeStructureRing( + algebra: A, + bufferFactory: MutableBufferFactory, + order: Int, + bindings: Map, +) : DerivativeStructureAlgebra(algebra, bufferFactory, order, bindings), + Ring>, ScaleOperations>, + NumericAlgebra>, + NumbersAddOps> where A : Ring, A : NumericAlgebra, A : ScaleOperations { + + override fun bindSymbolOrNull(value: String): DerivativeStructureSymbol? = + super.bindSymbolOrNull(value) + override fun DerivativeStructure.unaryMinus(): DerivativeStructure { - val ds = DerivativeStructure(this@DerivativeStructureRing, compiler) - for (i in ds.data.indices) { - ds.data[i] = algebra { -data[i] } - } - return ds + val newData = algebra { data.map(bufferFactory) { -it } } + return DerivativeStructure(this@DerivativeStructureRing, newData) } + /** + * Create a copy of given [Buffer] and modify it according to [block] + */ + protected inline fun DerivativeStructure.transformDataBuffer(block: DSCompiler.(MutableBuffer) -> Unit): DerivativeStructure { + val newData = bufferFactory(compiler.size) { data[it] } + compiler.block(newData) + return DerivativeStructure(this@DerivativeStructureRing, newData) + } + + protected fun DerivativeStructure.mapData(block: (T) -> T): DerivativeStructure { + val newData: Buffer = data.map(bufferFactory, block) + return DerivativeStructure(this@DerivativeStructureRing, newData) + } + + protected fun DerivativeStructure.mapDataIndexed(block: (Int, T) -> T): DerivativeStructure { + val newData: Buffer = data.mapIndexed(bufferFactory, block) + return DerivativeStructure(this@DerivativeStructureRing, newData) + } + + override val zero: DerivativeStructure by lazy { + const(algebra.zero) + } + + override val one: DerivativeStructure by lazy { + const(algebra.one) + } + + override fun number(value: Number): DerivativeStructure = const(algebra.number(value)) + override fun add(left: DerivativeStructure, right: DerivativeStructure): DerivativeStructure { left.compiler.checkCompatibility(right.compiler) - val ds = DerivativeStructure(left) - left.compiler.add(left.data, 0, right.data, 0, ds.data, 0) - return ds + return left.transformDataBuffer { result -> + add(left.data, 0, right.data, 0, result, 0) + } } - override fun scale(a: DerivativeStructure, value: Double): DerivativeStructure { - val ds = DerivativeStructure(a) - for (i in ds.data.indices) { - ds.data[i] = algebra { ds.data[i].times(value) } - } - return ds + override fun scale(a: DerivativeStructure, value: Double): DerivativeStructure = algebra { + a.mapData { it.times(value) } } override fun multiply( left: DerivativeStructure, - right: DerivativeStructure + right: DerivativeStructure, ): DerivativeStructure { left.compiler.checkCompatibility(right.compiler) - val result = DerivativeStructure(this, left.compiler) - left.compiler.multiply(left.data, 0, right.data, 0, result.data, 0) - return result + return left.transformDataBuffer { result -> + multiply(left.data, 0, right.data, 0, result, 0) + } } override fun DerivativeStructure.minus(arg: DerivativeStructure): DerivativeStructure { compiler.checkCompatibility(arg.compiler) - val ds = DerivativeStructure(this) - compiler.subtract(data, 0, arg.data, 0, ds.data, 0) - return ds + return transformDataBuffer { result -> + subtract(data, 0, arg.data, 0, result, 0) + } } - override operator fun DerivativeStructure.plus(other: Number): DerivativeStructure { - val ds = DerivativeStructure(this) - ds.data[0] = algebra { ds.data[0] + number(other) } - return ds + override operator fun DerivativeStructure.plus(other: Number): DerivativeStructure = algebra { + transformDataBuffer { + it[0] += number(other) + } } override operator fun DerivativeStructure.minus(other: Number): DerivativeStructure = - this + -other.toDouble() + this + (-other.toDouble()) override operator fun Number.plus(other: DerivativeStructure): DerivativeStructure = other + this override operator fun Number.minus(other: DerivativeStructure): DerivativeStructure = other - this @@ -194,119 +245,85 @@ public class DerivativeStructureField>( override fun divide(left: DerivativeStructure, right: DerivativeStructure): DerivativeStructure { left.compiler.checkCompatibility(right.compiler) - val result = DerivativeStructure(this, left.compiler) - left.compiler.divide(left.data, 0, right.data, 0, result.data, 0) - return result + return left.transformDataBuffer { result -> + left.compiler.divide(left.data, 0, right.data, 0, result, 0) + } } - override fun sin(arg: DerivativeStructure): DerivativeStructure { - val result = DerivativeStructure(this, arg.compiler) - arg.compiler.sin(arg.data, 0, result.data, 0) - return result + override fun sin(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> + sin(arg.data, 0, result, 0) } - override fun cos(arg: DerivativeStructure): DerivativeStructure { - val result = DerivativeStructure(this, arg.compiler) - arg.compiler.cos(arg.data, 0, result.data, 0) - return result + override fun cos(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> + cos(arg.data, 0, result, 0) } - override fun tan(arg: DerivativeStructure): DerivativeStructure { - val result = DerivativeStructure(this, arg.compiler) - arg.compiler.tan(arg.data, 0, result.data, 0) - return result + override fun tan(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> + tan(arg.data, 0, result, 0) } - override fun asin(arg: DerivativeStructure): DerivativeStructure { - val result = DerivativeStructure(this, arg.compiler) - arg.compiler.asin(arg.data, 0, result.data, 0) - return result + override fun asin(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> + asin(arg.data, 0, result, 0) } - override fun acos(arg: DerivativeStructure): DerivativeStructure { - val result = DerivativeStructure(this, arg.compiler) - arg.compiler.acos(arg.data, 0, result.data, 0) - return result + override fun acos(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> + acos(arg.data, 0, result, 0) } - override fun atan(arg: DerivativeStructure): DerivativeStructure { - val result = DerivativeStructure(this, arg.compiler) - arg.compiler.atan(arg.data, 0, result.data, 0) - return result + override fun atan(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> + atan(arg.data, 0, result, 0) } - override fun sinh(arg: DerivativeStructure): DerivativeStructure { - val result = DerivativeStructure(this, arg.compiler) - arg.compiler.sinh(arg.data, 0, result.data, 0) - return result + override fun sinh(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> + sinh(arg.data, 0, result, 0) } - override fun cosh(arg: DerivativeStructure): DerivativeStructure { - val result = DerivativeStructure(this, arg.compiler) - arg.compiler.cosh(arg.data, 0, result.data, 0) - return result + override fun cosh(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> + cosh(arg.data, 0, result, 0) } - override fun tanh(arg: DerivativeStructure): DerivativeStructure { - val result = DerivativeStructure(this, arg.compiler) - arg.compiler.tanh(arg.data, 0, result.data, 0) - return result + override fun tanh(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> + tanh(arg.data, 0, result, 0) } - override fun asinh(arg: DerivativeStructure): DerivativeStructure { - val result = DerivativeStructure(this, arg.compiler) - arg.compiler.asinh(arg.data, 0, result.data, 0) - return result + override fun asinh(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> + asinh(arg.data, 0, result, 0) } - override fun acosh(arg: DerivativeStructure): DerivativeStructure { - val result = DerivativeStructure(this, arg.compiler) - arg.compiler.acosh(arg.data, 0, result.data, 0) - return result + override fun acosh(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> + acosh(arg.data, 0, result, 0) } - override fun atanh(arg: DerivativeStructure): DerivativeStructure { - val result = DerivativeStructure(this, arg.compiler) - arg.compiler.atanh(arg.data, 0, result.data, 0) - return result + override fun atanh(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> + atanh(arg.data, 0, result, 0) } override fun power(arg: DerivativeStructure, pow: Number): DerivativeStructure = when (pow) { - is Int -> { - val result = DerivativeStructure(this, arg.compiler) - arg.compiler.pow(arg.data, 0, pow, result.data, 0) - result + is Int -> arg.transformDataBuffer { result -> + pow(arg.data, 0, pow, result, 0) } - else -> { - val result = DerivativeStructure(this, arg.compiler) - arg.compiler.pow(arg.data, 0, pow.toDouble(), result.data, 0) - result + else -> arg.transformDataBuffer { result -> + pow(arg.data, 0, pow.toDouble(), result, 0) } } - override fun sqrt(arg: DerivativeStructure): DerivativeStructure { - val result = DerivativeStructure(this, arg.compiler) - arg.compiler.sqrt(arg.data, 0, result.data, 0) - return result + override fun sqrt(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> + sqrt(arg.data, 0, result, 0) } public fun power(arg: DerivativeStructure, pow: DerivativeStructure): DerivativeStructure { arg.compiler.checkCompatibility(pow.compiler) - val result = DerivativeStructure(this, arg.compiler) - arg.compiler.pow(arg.data, 0, pow.data, 0, result.data, 0) - return result + return arg.transformDataBuffer { result -> + pow(arg.data, 0, pow.data, 0, result, 0) + } } - override fun exp(arg: DerivativeStructure): DerivativeStructure { - val result = DerivativeStructure(this, arg.compiler) - arg.compiler.exp(arg.data, 0, result.data, 0) - return result + override fun exp(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> + exp(arg.data, 0, result, 0) } - override fun ln(arg: DerivativeStructure): DerivativeStructure { - val result = DerivativeStructure(this, arg.compiler) - arg.compiler.ln(arg.data, 0, result.data, 0) - return result + override fun ln(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> + ln(arg.data, 0, result, 0) } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt index 715fad07b..10438dd02 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt @@ -188,7 +188,7 @@ public interface LinearSpace> { */ public fun > buffered( algebra: A, - bufferFactory: BufferFactory = Buffer.Companion::boxing, + bufferFactory: BufferFactory = BufferFactory(Buffer.Companion::boxing), ): LinearSpace = BufferedLinearSpace(BufferRingOps(algebra, bufferFactory)) @Deprecated("use DoubleField.linearSpace") diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt index 7c612b6a9..60fa81cd8 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 @@ -27,5 +27,5 @@ public annotation class UnstableKMathAPI RequiresOptIn.Level.WARNING, ) public annotation class PerformancePitfall( - val message: String = "Potential performance problem" + val message: String = "Potential performance problem", ) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt index 2401f6319..8175bd65e 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 @@ -69,7 +69,7 @@ public class MutableBufferND( * Transform structure to a new structure using provided [MutableBufferFactory] and optimizing if argument is [MutableBufferND] */ public inline fun MutableStructureND.mapToMutableBuffer( - factory: MutableBufferFactory = MutableBuffer.Companion::auto, + factory: MutableBufferFactory = MutableBufferFactory(MutableBuffer.Companion::auto), crossinline transform: (T) -> R, ): MutableBufferND { return if (this is MutableBufferND) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt index e934c6370..6e54e1b9d 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 @@ -120,7 +120,7 @@ public interface StructureND : Featured, WithShape { */ public fun buffered( strides: Strides, - bufferFactory: BufferFactory = Buffer.Companion::boxing, + bufferFactory: BufferFactory = BufferFactory(Buffer.Companion::boxing), initializer: (IntArray) -> T, ): BufferND = BufferND(strides, bufferFactory(strides.linearSize) { i -> initializer(strides.index(i)) }) @@ -140,7 +140,7 @@ public interface StructureND : Featured, WithShape { public fun buffered( shape: IntArray, - bufferFactory: BufferFactory = Buffer.Companion::boxing, + bufferFactory: BufferFactory = BufferFactory(Buffer.Companion::boxing), initializer: (IntArray) -> T, ): BufferND = buffered(DefaultStrides(shape), bufferFactory, initializer) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/DoubleBufferOps.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/DoubleBufferOps.kt index 0ee591acc..083892105 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,12 +6,10 @@ 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 kotlin.math.* /** @@ -21,7 +19,7 @@ public abstract class DoubleBufferOps : BufferAlgebra, Exte Norm, Double> { override val elementAlgebra: DoubleField get() = DoubleField - override val bufferFactory: BufferFactory get() = ::DoubleBuffer + override val bufferFactory: BufferFactory get() = BufferFactory(::DoubleBuffer) override fun Buffer.map(block: DoubleField.(Double) -> Double): DoubleBuffer = mapInline { DoubleField.block(it) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/bufferOperation.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/bufferOperation.kt index 31b0c2841..652472fcf 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,31 +61,39 @@ public inline fun Buffer.toTypedArray(): Array = Array(size, : /** * Create a new buffer from this one with the given mapping function and using [Buffer.Companion.auto] buffer factory. */ -public inline fun Buffer.map(block: (T) -> R): Buffer = +public inline fun Buffer.map(block: (T) -> R): Buffer = Buffer.auto(size) { block(get(it)) } /** * Create a new buffer from this one with the given mapping function. * Provided [bufferFactory] is used to construct the new buffer. */ -public inline fun Buffer.map( +public inline fun Buffer.map( bufferFactory: BufferFactory, crossinline block: (T) -> R, ): Buffer = bufferFactory(size) { block(get(it)) } /** - * Create a new buffer from this one with the given indexed mapping function. - * Provided [BufferFactory] is used to construct the new buffer. + * Create a new buffer from this one with the given mapping (indexed) function. + * Provided [bufferFactory] is used to construct the new buffer. */ -public inline fun Buffer.mapIndexed( - bufferFactory: BufferFactory = Buffer.Companion::auto, +public inline fun Buffer.mapIndexed( + bufferFactory: BufferFactory, crossinline block: (index: Int, value: T) -> R, ): Buffer = bufferFactory(size) { block(it, get(it)) } +/** + * Create a new buffer from this one with the given indexed mapping function. + * Provided [BufferFactory] is used to construct the new buffer. + */ +public inline fun Buffer.mapIndexed( + crossinline block: (index: Int, value: T) -> R, +): Buffer = BufferFactory(Buffer.Companion::auto).invoke(size) { block(it, get(it)) } + /** * Fold given buffer according to [operation] */ -public inline fun Buffer.fold(initial: R, operation: (acc: R, T) -> R): R { +public inline fun Buffer.fold(initial: R, operation: (acc: R, T) -> R): R { var accumulator = initial for (index in this.indices) accumulator = operation(accumulator, get(index)) return accumulator @@ -95,9 +103,9 @@ 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, + bufferFactory: BufferFactory = BufferFactory(Buffer.Companion::auto), crossinline transform: (T1, T2) -> R, ): Buffer { require(size == other.size) { "Buffer size mismatch in zip: expected $size but found ${other.size}" } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt index a1b0307c4..1c79c257a 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 @@ -14,14 +14,18 @@ import kotlin.reflect.KClass * * @param T the type of buffer. */ -public typealias BufferFactory = (Int, (Int) -> T) -> Buffer +public fun interface BufferFactory { + public operator fun invoke(size: Int, builder: (Int) -> T): Buffer +} /** * Function that produces [MutableBuffer] from its size and function that supplies values. * * @param T the type of buffer. */ -public typealias MutableBufferFactory = (Int, (Int) -> T) -> MutableBuffer +public fun interface MutableBufferFactory: BufferFactory{ + override fun invoke(size: Int, builder: (Int) -> T): MutableBuffer +} /** * A generic read-only random-access structure for both primitives and objects. diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt deleted file mode 100644 index aac327a84..000000000 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt +++ /dev/null @@ -1,1003 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. - */ - -/* This file is generated with buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt */ - -package space.kscience.kmath.ejml - -import org.ejml.data.* -import org.ejml.dense.row.CommonOps_DDRM -import org.ejml.dense.row.CommonOps_FDRM -import org.ejml.dense.row.factory.DecompositionFactory_DDRM -import org.ejml.dense.row.factory.DecompositionFactory_FDRM -import org.ejml.sparse.FillReducing -import org.ejml.sparse.csc.CommonOps_DSCC -import org.ejml.sparse.csc.CommonOps_FSCC -import org.ejml.sparse.csc.factory.DecompositionFactory_DSCC -import org.ejml.sparse.csc.factory.DecompositionFactory_FSCC -import org.ejml.sparse.csc.factory.LinearSolverFactory_DSCC -import org.ejml.sparse.csc.factory.LinearSolverFactory_FSCC -import space.kscience.kmath.linear.* -import space.kscience.kmath.linear.Matrix -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.nd.StructureFeature -import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.FloatField -import space.kscience.kmath.operations.invoke -import space.kscience.kmath.structures.DoubleBuffer -import space.kscience.kmath.structures.FloatBuffer -import kotlin.reflect.KClass -import kotlin.reflect.cast - -/** - * [EjmlVector] specialization for [Double]. - */ -public class EjmlDoubleVector(override val origin: M) : EjmlVector(origin) { - init { - require(origin.numRows == 1) { "The origin matrix must have only one row to form a vector" } - } - - override operator fun get(index: Int): Double = origin[0, index] -} - -/** - * [EjmlVector] specialization for [Float]. - */ -public class EjmlFloatVector(override val origin: M) : EjmlVector(origin) { - init { - require(origin.numRows == 1) { "The origin matrix must have only one row to form a vector" } - } - - override operator fun get(index: Int): Float = origin[0, index] -} - -/** - * [EjmlMatrix] specialization for [Double]. - */ -public class EjmlDoubleMatrix(override val origin: M) : EjmlMatrix(origin) { - override operator fun get(i: Int, j: Int): Double = origin[i, j] -} - -/** - * [EjmlMatrix] specialization for [Float]. - */ -public class EjmlFloatMatrix(override val origin: M) : EjmlMatrix(origin) { - override operator fun get(i: Int, j: Int): Float = origin[i, j] -} - -/** - * [EjmlLinearSpace] implementation based on [CommonOps_DDRM], [DecompositionFactory_DDRM] operations and - * [DMatrixRMaj] matrices. - */ -public object EjmlLinearSpaceDDRM : EjmlLinearSpace() { - /** - * The [DoubleField] reference. - */ - override val elementAlgebra: DoubleField get() = DoubleField - - @Suppress("UNCHECKED_CAST") - override fun Matrix.toEjml(): EjmlDoubleMatrix = when { - this is EjmlDoubleMatrix<*> && origin is DMatrixRMaj -> this as EjmlDoubleMatrix - else -> buildMatrix(rowNum, colNum) { i, j -> get(i, j) } - } - - @Suppress("UNCHECKED_CAST") - override fun Point.toEjml(): EjmlDoubleVector = when { - this is EjmlDoubleVector<*> && origin is DMatrixRMaj -> this as EjmlDoubleVector - else -> EjmlDoubleVector(DMatrixRMaj(size, 1).also { - (0 until it.numRows).forEach { row -> it[row, 0] = get(row) } - }) - } - - override fun buildMatrix( - rows: Int, - columns: Int, - initializer: DoubleField.(i: Int, j: Int) -> Double, - ): EjmlDoubleMatrix = DMatrixRMaj(rows, columns).also { - (0 until rows).forEach { row -> - (0 until columns).forEach { col -> it[row, col] = elementAlgebra.initializer(row, col) } - } - }.wrapMatrix() - - override fun buildVector( - size: Int, - initializer: DoubleField.(Int) -> Double, - ): EjmlDoubleVector = EjmlDoubleVector(DMatrixRMaj(size, 1).also { - (0 until it.numRows).forEach { row -> it[row, 0] = elementAlgebra.initializer(row) } - }) - - private fun T.wrapMatrix() = EjmlDoubleMatrix(this) - private fun T.wrapVector() = EjmlDoubleVector(this) - - override fun Matrix.unaryMinus(): Matrix = this * elementAlgebra { -one } - - override fun Matrix.dot(other: Matrix): EjmlDoubleMatrix { - val out = DMatrixRMaj(1, 1) - CommonOps_DDRM.mult(toEjml().origin, other.toEjml().origin, out) - return out.wrapMatrix() - } - - override fun Matrix.dot(vector: Point): EjmlDoubleVector { - val out = DMatrixRMaj(1, 1) - CommonOps_DDRM.mult(toEjml().origin, vector.toEjml().origin, out) - return out.wrapVector() - } - - override operator fun Matrix.minus(other: Matrix): EjmlDoubleMatrix { - val out = DMatrixRMaj(1, 1) - - CommonOps_DDRM.add( - elementAlgebra.one, - toEjml().origin, - elementAlgebra { -one }, - other.toEjml().origin, - out, - ) - - return out.wrapMatrix() - } - - override operator fun Matrix.times(value: Double): EjmlDoubleMatrix { - val res = DMatrixRMaj(1, 1) - CommonOps_DDRM.scale(value, toEjml().origin, res) - return res.wrapMatrix() - } - - override fun Point.unaryMinus(): EjmlDoubleVector { - val res = DMatrixRMaj(1, 1) - CommonOps_DDRM.changeSign(toEjml().origin, res) - return res.wrapVector() - } - - override fun Matrix.plus(other: Matrix): EjmlDoubleMatrix { - val out = DMatrixRMaj(1, 1) - - CommonOps_DDRM.add( - elementAlgebra.one, - toEjml().origin, - elementAlgebra.one, - other.toEjml().origin, - out, - ) - - return out.wrapMatrix() - } - - override fun Point.plus(other: Point): EjmlDoubleVector { - val out = DMatrixRMaj(1, 1) - - CommonOps_DDRM.add( - elementAlgebra.one, - toEjml().origin, - elementAlgebra.one, - other.toEjml().origin, - out, - ) - - return out.wrapVector() - } - - override fun Point.minus(other: Point): EjmlDoubleVector { - val out = DMatrixRMaj(1, 1) - - CommonOps_DDRM.add( - elementAlgebra.one, - toEjml().origin, - elementAlgebra { -one }, - other.toEjml().origin, - out, - ) - - return out.wrapVector() - } - - override fun Double.times(m: Matrix): EjmlDoubleMatrix = m * this - - override fun Point.times(value: Double): EjmlDoubleVector { - val res = DMatrixRMaj(1, 1) - CommonOps_DDRM.scale(value, toEjml().origin, res) - return res.wrapVector() - } - - override fun Double.times(v: Point): EjmlDoubleVector = v * this - - @UnstableKMathAPI - override fun computeFeature(structure: Matrix, type: KClass): F? { - structure.getFeature(type)?.let { return it } - val origin = structure.toEjml().origin - - return when (type) { - InverseMatrixFeature::class -> object : InverseMatrixFeature { - override val inverse: Matrix by lazy { - val res = origin.copy() - CommonOps_DDRM.invert(res) - res.wrapMatrix() - } - } - - DeterminantFeature::class -> object : DeterminantFeature { - override val determinant: Double by lazy { CommonOps_DDRM.det(origin) } - } - - SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature { - private val svd by lazy { - DecompositionFactory_DDRM.svd(origin.numRows, origin.numCols, true, true, false) - .apply { decompose(origin.copy()) } - } - - override val u: Matrix by lazy { svd.getU(null, false).wrapMatrix() } - override val s: Matrix by lazy { svd.getW(null).wrapMatrix() } - override val v: Matrix by lazy { svd.getV(null, false).wrapMatrix() } - override val singularValues: Point by lazy { DoubleBuffer(svd.singularValues) } - } - - QRDecompositionFeature::class -> object : QRDecompositionFeature { - private val qr by lazy { - DecompositionFactory_DDRM.qr().apply { decompose(origin.copy()) } - } - - override val q: Matrix by lazy { - qr.getQ(null, false).wrapMatrix().withFeature(OrthogonalFeature) - } - - override val r: Matrix by lazy { qr.getR(null, false).wrapMatrix().withFeature(UFeature) } - } - - CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature { - override val l: Matrix by lazy { - val cholesky = - DecompositionFactory_DDRM.chol(structure.rowNum, true).apply { decompose(origin.copy()) } - - cholesky.getT(null).wrapMatrix().withFeature(LFeature) - } - } - - LupDecompositionFeature::class -> object : LupDecompositionFeature { - private val lup by lazy { - DecompositionFactory_DDRM.lu(origin.numRows, origin.numCols).apply { decompose(origin.copy()) } - } - - override val l: Matrix by lazy { - lup.getLower(null).wrapMatrix().withFeature(LFeature) - } - - override val u: Matrix by lazy { - lup.getUpper(null).wrapMatrix().withFeature(UFeature) - } - - override val p: Matrix by lazy { lup.getRowPivot(null).wrapMatrix() } - } - - else -> null - }?.let{ - type.cast(it) - } - } - - /** - * Solves for *x* in the following equation: *x = [a] -1 · [b]*. - * - * @param a the base matrix. - * @param b n by p matrix. - * @return the solution for *x* that is n by p. - */ - public fun solve(a: Matrix, b: Matrix): EjmlDoubleMatrix { - val res = DMatrixRMaj(1, 1) - CommonOps_DDRM.solve(DMatrixRMaj(a.toEjml().origin), DMatrixRMaj(b.toEjml().origin), res) - return res.wrapMatrix() - } - - /** - * Solves for *x* in the following equation: *x = [a] -1 · [b]*. - * - * @param a the base matrix. - * @param b n by p vector. - * @return the solution for *x* that is n by p. - */ - public fun solve(a: Matrix, b: Point): EjmlDoubleVector { - val res = DMatrixRMaj(1, 1) - CommonOps_DDRM.solve(DMatrixRMaj(a.toEjml().origin), DMatrixRMaj(b.toEjml().origin), res) - return EjmlDoubleVector(res) - } -} - -/** - * [EjmlLinearSpace] implementation based on [CommonOps_FDRM], [DecompositionFactory_FDRM] operations and - * [FMatrixRMaj] matrices. - */ -public object EjmlLinearSpaceFDRM : EjmlLinearSpace() { - /** - * The [FloatField] reference. - */ - override val elementAlgebra: FloatField get() = FloatField - - @Suppress("UNCHECKED_CAST") - override fun Matrix.toEjml(): EjmlFloatMatrix = when { - this is EjmlFloatMatrix<*> && origin is FMatrixRMaj -> this as EjmlFloatMatrix - else -> buildMatrix(rowNum, colNum) { i, j -> get(i, j) } - } - - @Suppress("UNCHECKED_CAST") - override fun Point.toEjml(): EjmlFloatVector = when { - this is EjmlFloatVector<*> && origin is FMatrixRMaj -> this as EjmlFloatVector - else -> EjmlFloatVector(FMatrixRMaj(size, 1).also { - (0 until it.numRows).forEach { row -> it[row, 0] = get(row) } - }) - } - - override fun buildMatrix( - rows: Int, - columns: Int, - initializer: FloatField.(i: Int, j: Int) -> Float, - ): EjmlFloatMatrix = FMatrixRMaj(rows, columns).also { - (0 until rows).forEach { row -> - (0 until columns).forEach { col -> it[row, col] = elementAlgebra.initializer(row, col) } - } - }.wrapMatrix() - - override fun buildVector( - size: Int, - initializer: FloatField.(Int) -> Float, - ): EjmlFloatVector = EjmlFloatVector(FMatrixRMaj(size, 1).also { - (0 until it.numRows).forEach { row -> it[row, 0] = elementAlgebra.initializer(row) } - }) - - private fun T.wrapMatrix() = EjmlFloatMatrix(this) - private fun T.wrapVector() = EjmlFloatVector(this) - - override fun Matrix.unaryMinus(): Matrix = this * elementAlgebra { -one } - - override fun Matrix.dot(other: Matrix): EjmlFloatMatrix { - val out = FMatrixRMaj(1, 1) - CommonOps_FDRM.mult(toEjml().origin, other.toEjml().origin, out) - return out.wrapMatrix() - } - - override fun Matrix.dot(vector: Point): EjmlFloatVector { - val out = FMatrixRMaj(1, 1) - CommonOps_FDRM.mult(toEjml().origin, vector.toEjml().origin, out) - return out.wrapVector() - } - - override operator fun Matrix.minus(other: Matrix): EjmlFloatMatrix { - val out = FMatrixRMaj(1, 1) - - CommonOps_FDRM.add( - elementAlgebra.one, - toEjml().origin, - elementAlgebra { -one }, - other.toEjml().origin, - out, - ) - - return out.wrapMatrix() - } - - override operator fun Matrix.times(value: Float): EjmlFloatMatrix { - val res = FMatrixRMaj(1, 1) - CommonOps_FDRM.scale(value, toEjml().origin, res) - return res.wrapMatrix() - } - - override fun Point.unaryMinus(): EjmlFloatVector { - val res = FMatrixRMaj(1, 1) - CommonOps_FDRM.changeSign(toEjml().origin, res) - return res.wrapVector() - } - - override fun Matrix.plus(other: Matrix): EjmlFloatMatrix { - val out = FMatrixRMaj(1, 1) - - CommonOps_FDRM.add( - elementAlgebra.one, - toEjml().origin, - elementAlgebra.one, - other.toEjml().origin, - out, - ) - - return out.wrapMatrix() - } - - override fun Point.plus(other: Point): EjmlFloatVector { - val out = FMatrixRMaj(1, 1) - - CommonOps_FDRM.add( - elementAlgebra.one, - toEjml().origin, - elementAlgebra.one, - other.toEjml().origin, - out, - ) - - return out.wrapVector() - } - - override fun Point.minus(other: Point): EjmlFloatVector { - val out = FMatrixRMaj(1, 1) - - CommonOps_FDRM.add( - elementAlgebra.one, - toEjml().origin, - elementAlgebra { -one }, - other.toEjml().origin, - out, - ) - - return out.wrapVector() - } - - override fun Float.times(m: Matrix): EjmlFloatMatrix = m * this - - override fun Point.times(value: Float): EjmlFloatVector { - val res = FMatrixRMaj(1, 1) - CommonOps_FDRM.scale(value, toEjml().origin, res) - return res.wrapVector() - } - - override fun Float.times(v: Point): EjmlFloatVector = v * this - - @UnstableKMathAPI - override fun computeFeature(structure: Matrix, type: KClass): F? { - structure.getFeature(type)?.let { return it } - val origin = structure.toEjml().origin - - return when (type) { - InverseMatrixFeature::class -> object : InverseMatrixFeature { - override val inverse: Matrix by lazy { - val res = origin.copy() - CommonOps_FDRM.invert(res) - res.wrapMatrix() - } - } - - DeterminantFeature::class -> object : DeterminantFeature { - override val determinant: Float by lazy { CommonOps_FDRM.det(origin) } - } - - SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature { - private val svd by lazy { - DecompositionFactory_FDRM.svd(origin.numRows, origin.numCols, true, true, false) - .apply { decompose(origin.copy()) } - } - - override val u: Matrix by lazy { svd.getU(null, false).wrapMatrix() } - override val s: Matrix by lazy { svd.getW(null).wrapMatrix() } - override val v: Matrix by lazy { svd.getV(null, false).wrapMatrix() } - override val singularValues: Point by lazy { FloatBuffer(svd.singularValues) } - } - - QRDecompositionFeature::class -> object : QRDecompositionFeature { - private val qr by lazy { - DecompositionFactory_FDRM.qr().apply { decompose(origin.copy()) } - } - - override val q: Matrix by lazy { - qr.getQ(null, false).wrapMatrix().withFeature(OrthogonalFeature) - } - - override val r: Matrix by lazy { qr.getR(null, false).wrapMatrix().withFeature(UFeature) } - } - - CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature { - override val l: Matrix by lazy { - val cholesky = - DecompositionFactory_FDRM.chol(structure.rowNum, true).apply { decompose(origin.copy()) } - - cholesky.getT(null).wrapMatrix().withFeature(LFeature) - } - } - - LupDecompositionFeature::class -> object : LupDecompositionFeature { - private val lup by lazy { - DecompositionFactory_FDRM.lu(origin.numRows, origin.numCols).apply { decompose(origin.copy()) } - } - - override val l: Matrix by lazy { - lup.getLower(null).wrapMatrix().withFeature(LFeature) - } - - override val u: Matrix by lazy { - lup.getUpper(null).wrapMatrix().withFeature(UFeature) - } - - override val p: Matrix by lazy { lup.getRowPivot(null).wrapMatrix() } - } - - else -> null - }?.let{ - type.cast(it) - } - } - - /** - * Solves for *x* in the following equation: *x = [a] -1 · [b]*. - * - * @param a the base matrix. - * @param b n by p matrix. - * @return the solution for *x* that is n by p. - */ - public fun solve(a: Matrix, b: Matrix): EjmlFloatMatrix { - val res = FMatrixRMaj(1, 1) - CommonOps_FDRM.solve(FMatrixRMaj(a.toEjml().origin), FMatrixRMaj(b.toEjml().origin), res) - return res.wrapMatrix() - } - - /** - * Solves for *x* in the following equation: *x = [a] -1 · [b]*. - * - * @param a the base matrix. - * @param b n by p vector. - * @return the solution for *x* that is n by p. - */ - public fun solve(a: Matrix, b: Point): EjmlFloatVector { - val res = FMatrixRMaj(1, 1) - CommonOps_FDRM.solve(FMatrixRMaj(a.toEjml().origin), FMatrixRMaj(b.toEjml().origin), res) - return EjmlFloatVector(res) - } -} - -/** - * [EjmlLinearSpace] implementation based on [CommonOps_DSCC], [DecompositionFactory_DSCC] operations and - * [DMatrixSparseCSC] matrices. - */ -public object EjmlLinearSpaceDSCC : EjmlLinearSpace() { - /** - * The [DoubleField] reference. - */ - override val elementAlgebra: DoubleField get() = DoubleField - - @Suppress("UNCHECKED_CAST") - override fun Matrix.toEjml(): EjmlDoubleMatrix = when { - this is EjmlDoubleMatrix<*> && origin is DMatrixSparseCSC -> this as EjmlDoubleMatrix - else -> buildMatrix(rowNum, colNum) { i, j -> get(i, j) } - } - - @Suppress("UNCHECKED_CAST") - override fun Point.toEjml(): EjmlDoubleVector = when { - this is EjmlDoubleVector<*> && origin is DMatrixSparseCSC -> this as EjmlDoubleVector - else -> EjmlDoubleVector(DMatrixSparseCSC(size, 1).also { - (0 until it.numRows).forEach { row -> it[row, 0] = get(row) } - }) - } - - override fun buildMatrix( - rows: Int, - columns: Int, - initializer: DoubleField.(i: Int, j: Int) -> Double, - ): EjmlDoubleMatrix = DMatrixSparseCSC(rows, columns).also { - (0 until rows).forEach { row -> - (0 until columns).forEach { col -> it[row, col] = elementAlgebra.initializer(row, col) } - } - }.wrapMatrix() - - override fun buildVector( - size: Int, - initializer: DoubleField.(Int) -> Double, - ): EjmlDoubleVector = EjmlDoubleVector(DMatrixSparseCSC(size, 1).also { - (0 until it.numRows).forEach { row -> it[row, 0] = elementAlgebra.initializer(row) } - }) - - private fun T.wrapMatrix() = EjmlDoubleMatrix(this) - private fun T.wrapVector() = EjmlDoubleVector(this) - - override fun Matrix.unaryMinus(): Matrix = this * elementAlgebra { -one } - - override fun Matrix.dot(other: Matrix): EjmlDoubleMatrix { - val out = DMatrixSparseCSC(1, 1) - CommonOps_DSCC.mult(toEjml().origin, other.toEjml().origin, out) - return out.wrapMatrix() - } - - override fun Matrix.dot(vector: Point): EjmlDoubleVector { - val out = DMatrixSparseCSC(1, 1) - CommonOps_DSCC.mult(toEjml().origin, vector.toEjml().origin, out) - return out.wrapVector() - } - - override operator fun Matrix.minus(other: Matrix): EjmlDoubleMatrix { - val out = DMatrixSparseCSC(1, 1) - - CommonOps_DSCC.add( - elementAlgebra.one, - toEjml().origin, - elementAlgebra { -one }, - other.toEjml().origin, - out, - null, - null, - ) - - return out.wrapMatrix() - } - - override operator fun Matrix.times(value: Double): EjmlDoubleMatrix { - val res = DMatrixSparseCSC(1, 1) - CommonOps_DSCC.scale(value, toEjml().origin, res) - return res.wrapMatrix() - } - - override fun Point.unaryMinus(): EjmlDoubleVector { - val res = DMatrixSparseCSC(1, 1) - CommonOps_DSCC.changeSign(toEjml().origin, res) - return res.wrapVector() - } - - override fun Matrix.plus(other: Matrix): EjmlDoubleMatrix { - val out = DMatrixSparseCSC(1, 1) - - CommonOps_DSCC.add( - elementAlgebra.one, - toEjml().origin, - elementAlgebra.one, - other.toEjml().origin, - out, - null, - null, - ) - - return out.wrapMatrix() - } - - override fun Point.plus(other: Point): EjmlDoubleVector { - val out = DMatrixSparseCSC(1, 1) - - CommonOps_DSCC.add( - elementAlgebra.one, - toEjml().origin, - elementAlgebra.one, - other.toEjml().origin, - out, - null, - null, - ) - - return out.wrapVector() - } - - override fun Point.minus(other: Point): EjmlDoubleVector { - val out = DMatrixSparseCSC(1, 1) - - CommonOps_DSCC.add( - elementAlgebra.one, - toEjml().origin, - elementAlgebra { -one }, - other.toEjml().origin, - out, - null, - null, - ) - - return out.wrapVector() - } - - override fun Double.times(m: Matrix): EjmlDoubleMatrix = m * this - - override fun Point.times(value: Double): EjmlDoubleVector { - val res = DMatrixSparseCSC(1, 1) - CommonOps_DSCC.scale(value, toEjml().origin, res) - return res.wrapVector() - } - - override fun Double.times(v: Point): EjmlDoubleVector = v * this - - @UnstableKMathAPI - override fun computeFeature(structure: Matrix, type: KClass): F? { - structure.getFeature(type)?.let { return it } - val origin = structure.toEjml().origin - - return when (type) { - QRDecompositionFeature::class -> object : QRDecompositionFeature { - private val qr by lazy { - DecompositionFactory_DSCC.qr(FillReducing.NONE).apply { decompose(origin.copy()) } - } - - override val q: Matrix by lazy { - qr.getQ(null, false).wrapMatrix().withFeature(OrthogonalFeature) - } - - override val r: Matrix by lazy { qr.getR(null, false).wrapMatrix().withFeature(UFeature) } - } - - CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature { - override val l: Matrix by lazy { - val cholesky = - DecompositionFactory_DSCC.cholesky().apply { decompose(origin.copy()) } - - (cholesky.getT(null) as DMatrix).wrapMatrix().withFeature(LFeature) - } - } - - LUDecompositionFeature::class, DeterminantFeature::class, InverseMatrixFeature::class -> object : - LUDecompositionFeature, DeterminantFeature, InverseMatrixFeature { - private val lu by lazy { - DecompositionFactory_DSCC.lu(FillReducing.NONE).apply { decompose(origin.copy()) } - } - - override val l: Matrix by lazy { - lu.getLower(null).wrapMatrix().withFeature(LFeature) - } - - override val u: Matrix by lazy { - lu.getUpper(null).wrapMatrix().withFeature(UFeature) - } - - override val inverse: Matrix by lazy { - var a = origin - val inverse = DMatrixRMaj(1, 1) - val solver = LinearSolverFactory_DSCC.lu(FillReducing.NONE) - if (solver.modifiesA()) a = a.copy() - val i = CommonOps_DDRM.identity(a.numRows) - solver.solve(i, inverse) - inverse.wrapMatrix() - } - - override val determinant: Double by lazy { elementAlgebra.number(lu.computeDeterminant().real) } - } - - else -> null - }?.let{ - type.cast(it) - } - } - - /** - * Solves for *x* in the following equation: *x = [a] -1 · [b]*. - * - * @param a the base matrix. - * @param b n by p matrix. - * @return the solution for *x* that is n by p. - */ - public fun solve(a: Matrix, b: Matrix): EjmlDoubleMatrix { - val res = DMatrixSparseCSC(1, 1) - CommonOps_DSCC.solve(DMatrixSparseCSC(a.toEjml().origin), DMatrixSparseCSC(b.toEjml().origin), res) - return res.wrapMatrix() - } - - /** - * Solves for *x* in the following equation: *x = [a] -1 · [b]*. - * - * @param a the base matrix. - * @param b n by p vector. - * @return the solution for *x* that is n by p. - */ - public fun solve(a: Matrix, b: Point): EjmlDoubleVector { - val res = DMatrixSparseCSC(1, 1) - CommonOps_DSCC.solve(DMatrixSparseCSC(a.toEjml().origin), DMatrixSparseCSC(b.toEjml().origin), res) - return EjmlDoubleVector(res) - } -} - -/** - * [EjmlLinearSpace] implementation based on [CommonOps_FSCC], [DecompositionFactory_FSCC] operations and - * [FMatrixSparseCSC] matrices. - */ -public object EjmlLinearSpaceFSCC : EjmlLinearSpace() { - /** - * The [FloatField] reference. - */ - override val elementAlgebra: FloatField get() = FloatField - - @Suppress("UNCHECKED_CAST") - override fun Matrix.toEjml(): EjmlFloatMatrix = when { - this is EjmlFloatMatrix<*> && origin is FMatrixSparseCSC -> this as EjmlFloatMatrix - else -> buildMatrix(rowNum, colNum) { i, j -> get(i, j) } - } - - @Suppress("UNCHECKED_CAST") - override fun Point.toEjml(): EjmlFloatVector = when { - this is EjmlFloatVector<*> && origin is FMatrixSparseCSC -> this as EjmlFloatVector - else -> EjmlFloatVector(FMatrixSparseCSC(size, 1).also { - (0 until it.numRows).forEach { row -> it[row, 0] = get(row) } - }) - } - - override fun buildMatrix( - rows: Int, - columns: Int, - initializer: FloatField.(i: Int, j: Int) -> Float, - ): EjmlFloatMatrix = FMatrixSparseCSC(rows, columns).also { - (0 until rows).forEach { row -> - (0 until columns).forEach { col -> it[row, col] = elementAlgebra.initializer(row, col) } - } - }.wrapMatrix() - - override fun buildVector( - size: Int, - initializer: FloatField.(Int) -> Float, - ): EjmlFloatVector = EjmlFloatVector(FMatrixSparseCSC(size, 1).also { - (0 until it.numRows).forEach { row -> it[row, 0] = elementAlgebra.initializer(row) } - }) - - private fun T.wrapMatrix() = EjmlFloatMatrix(this) - private fun T.wrapVector() = EjmlFloatVector(this) - - override fun Matrix.unaryMinus(): Matrix = this * elementAlgebra { -one } - - override fun Matrix.dot(other: Matrix): EjmlFloatMatrix { - val out = FMatrixSparseCSC(1, 1) - CommonOps_FSCC.mult(toEjml().origin, other.toEjml().origin, out) - return out.wrapMatrix() - } - - override fun Matrix.dot(vector: Point): EjmlFloatVector { - val out = FMatrixSparseCSC(1, 1) - CommonOps_FSCC.mult(toEjml().origin, vector.toEjml().origin, out) - return out.wrapVector() - } - - override operator fun Matrix.minus(other: Matrix): EjmlFloatMatrix { - val out = FMatrixSparseCSC(1, 1) - - CommonOps_FSCC.add( - elementAlgebra.one, - toEjml().origin, - elementAlgebra { -one }, - other.toEjml().origin, - out, - null, - null, - ) - - return out.wrapMatrix() - } - - override operator fun Matrix.times(value: Float): EjmlFloatMatrix { - val res = FMatrixSparseCSC(1, 1) - CommonOps_FSCC.scale(value, toEjml().origin, res) - return res.wrapMatrix() - } - - override fun Point.unaryMinus(): EjmlFloatVector { - val res = FMatrixSparseCSC(1, 1) - CommonOps_FSCC.changeSign(toEjml().origin, res) - return res.wrapVector() - } - - override fun Matrix.plus(other: Matrix): EjmlFloatMatrix { - val out = FMatrixSparseCSC(1, 1) - - CommonOps_FSCC.add( - elementAlgebra.one, - toEjml().origin, - elementAlgebra.one, - other.toEjml().origin, - out, - null, - null, - ) - - return out.wrapMatrix() - } - - override fun Point.plus(other: Point): EjmlFloatVector { - val out = FMatrixSparseCSC(1, 1) - - CommonOps_FSCC.add( - elementAlgebra.one, - toEjml().origin, - elementAlgebra.one, - other.toEjml().origin, - out, - null, - null, - ) - - return out.wrapVector() - } - - override fun Point.minus(other: Point): EjmlFloatVector { - val out = FMatrixSparseCSC(1, 1) - - CommonOps_FSCC.add( - elementAlgebra.one, - toEjml().origin, - elementAlgebra { -one }, - other.toEjml().origin, - out, - null, - null, - ) - - return out.wrapVector() - } - - override fun Float.times(m: Matrix): EjmlFloatMatrix = m * this - - override fun Point.times(value: Float): EjmlFloatVector { - val res = FMatrixSparseCSC(1, 1) - CommonOps_FSCC.scale(value, toEjml().origin, res) - return res.wrapVector() - } - - override fun Float.times(v: Point): EjmlFloatVector = v * this - - @UnstableKMathAPI - override fun computeFeature(structure: Matrix, type: KClass): F? { - structure.getFeature(type)?.let { return it } - val origin = structure.toEjml().origin - - return when (type) { - QRDecompositionFeature::class -> object : QRDecompositionFeature { - private val qr by lazy { - DecompositionFactory_FSCC.qr(FillReducing.NONE).apply { decompose(origin.copy()) } - } - - override val q: Matrix by lazy { - qr.getQ(null, false).wrapMatrix().withFeature(OrthogonalFeature) - } - - override val r: Matrix by lazy { qr.getR(null, false).wrapMatrix().withFeature(UFeature) } - } - - CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature { - override val l: Matrix by lazy { - val cholesky = - DecompositionFactory_FSCC.cholesky().apply { decompose(origin.copy()) } - - (cholesky.getT(null) as FMatrix).wrapMatrix().withFeature(LFeature) - } - } - - LUDecompositionFeature::class, DeterminantFeature::class, InverseMatrixFeature::class -> object : - LUDecompositionFeature, DeterminantFeature, InverseMatrixFeature { - private val lu by lazy { - DecompositionFactory_FSCC.lu(FillReducing.NONE).apply { decompose(origin.copy()) } - } - - override val l: Matrix by lazy { - lu.getLower(null).wrapMatrix().withFeature(LFeature) - } - - override val u: Matrix by lazy { - lu.getUpper(null).wrapMatrix().withFeature(UFeature) - } - - override val inverse: Matrix by lazy { - var a = origin - val inverse = FMatrixRMaj(1, 1) - val solver = LinearSolverFactory_FSCC.lu(FillReducing.NONE) - if (solver.modifiesA()) a = a.copy() - val i = CommonOps_FDRM.identity(a.numRows) - solver.solve(i, inverse) - inverse.wrapMatrix() - } - - override val determinant: Float by lazy { elementAlgebra.number(lu.computeDeterminant().real) } - } - - else -> null - }?.let{ - type.cast(it) - } - } - - /** - * Solves for *x* in the following equation: *x = [a] -1 · [b]*. - * - * @param a the base matrix. - * @param b n by p matrix. - * @return the solution for *x* that is n by p. - */ - public fun solve(a: Matrix, b: Matrix): EjmlFloatMatrix { - val res = FMatrixSparseCSC(1, 1) - CommonOps_FSCC.solve(FMatrixSparseCSC(a.toEjml().origin), FMatrixSparseCSC(b.toEjml().origin), res) - return res.wrapMatrix() - } - - /** - * Solves for *x* in the following equation: *x = [a] -1 · [b]*. - * - * @param a the base matrix. - * @param b n by p vector. - * @return the solution for *x* that is n by p. - */ - public fun solve(a: Matrix, b: Point): EjmlFloatVector { - val res = FMatrixSparseCSC(1, 1) - CommonOps_FSCC.solve(FMatrixSparseCSC(a.toEjml().origin), FMatrixSparseCSC(b.toEjml().origin), res) - return EjmlFloatVector(res) - } -} - diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogramGroupND.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogramGroupND.kt index 90ec29ce3..eafd55513 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 @@ -28,7 +28,7 @@ public class UniformHistogramGroupND>( private val lower: Buffer, private val upper: Buffer, private val binNums: IntArray = IntArray(lower.size) { 20 }, - private val bufferFactory: BufferFactory = Buffer.Companion::boxing, + private val bufferFactory: BufferFactory = BufferFactory(Buffer.Companion::boxing), ) : HistogramGroupND { init { @@ -114,7 +114,7 @@ public class UniformHistogramGroupND>( public fun > Histogram.Companion.uniformNDFromRanges( valueAlgebraND: FieldOpsND, vararg ranges: ClosedFloatingPointRange, - bufferFactory: BufferFactory = Buffer.Companion::boxing, + bufferFactory: BufferFactory = BufferFactory(Buffer.Companion::boxing), ): UniformHistogramGroupND = UniformHistogramGroupND( valueAlgebraND, ranges.map(ClosedFloatingPointRange::start).asBuffer(), @@ -140,7 +140,7 @@ public fun Histogram.Companion.uniformDoubleNDFromRanges( public fun > Histogram.Companion.uniformNDFromRanges( valueAlgebraND: FieldOpsND, vararg ranges: Pair, Int>, - bufferFactory: BufferFactory = Buffer.Companion::boxing, + bufferFactory: BufferFactory = BufferFactory(Buffer.Companion::boxing), ): UniformHistogramGroupND = UniformHistogramGroupND( valueAlgebraND, ListBuffer( diff --git a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt b/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt index 1dc318517..0de2d8349 100644 --- a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt +++ b/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt @@ -6,6 +6,7 @@ package space.kscience.kmath.multik import org.jetbrains.kotlinx.multik.ndarray.data.DataType +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.ExponentialOperations @@ -22,10 +23,13 @@ public object MultikDoubleAlgebra : MultikDivisionTensorAlgebra): MultikTensor = sin(arg) / cos(arg) + @PerformancePitfall override fun asin(arg: StructureND): MultikTensor = arg.map { asin(it) } + @PerformancePitfall override fun acos(arg: StructureND): MultikTensor = arg.map { acos(it) } + @PerformancePitfall override fun atan(arg: StructureND): MultikTensor = arg.map { atan(it) } override fun exp(arg: StructureND): MultikTensor = multikMath.mathEx.exp(arg.asMultik().array).wrap() @@ -42,10 +46,13 @@ public object MultikDoubleAlgebra : MultikDivisionTensorAlgebra): MultikTensor = arg.map { asinh(it) } + @PerformancePitfall override fun acosh(arg: StructureND): MultikTensor = arg.map { acosh(it) } + @PerformancePitfall override fun atanh(arg: StructureND): MultikTensor = arg.map { atanh(it) } } diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt index a88f3e437..890318e31 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt @@ -35,7 +35,7 @@ public fun interface Sampler { public fun Sampler.sampleBuffer( generator: RandomGenerator, size: Int, - bufferFactory: BufferFactory = Buffer.Companion::boxing, + bufferFactory: BufferFactory = BufferFactory(Buffer.Companion::boxing), ): Chain> { require(size > 1) //creating temporary storage once -- 2.34.1 From f5fe53a9f234edd47ecb2e7d73e7700e12f4a01c Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 15 Jul 2022 16:20:28 +0300 Subject: [PATCH 132/275] Grand derivative refactoring. Phase 2 --- .../kscience/kmath/expressions/DSAlgebra.kt | 437 ++++++++++++++++++ .../kmath/expressions/DerivativeStructure.kt | 157 ------- .../DerivativeStructureExpression.kt | 349 -------------- .../DerivativeStructureExpressionTest.kt | 4 +- 4 files changed, 439 insertions(+), 508 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DSAlgebra.kt delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DerivativeStructure.kt delete mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpression.kt diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DSAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DSAlgebra.kt new file mode 100644 index 000000000..d9fc46b47 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DSAlgebra.kt @@ -0,0 +1,437 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + */ + +package space.kscience.kmath.expressions + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.* +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.MutableBuffer +import space.kscience.kmath.structures.MutableBufferFactory +import space.kscience.kmath.structures.asBuffer +import kotlin.math.max +import kotlin.math.min + +/** + * Class representing both the value and the differentials of a function. + * + * This class is the workhorse of the differentiation package. + * + * This class is an implementation of the extension to Rall's numbers described in Dan Kalman's paper + * [Doubly Recursive Multivariate Automatic Differentiation](http://www1.american.edu/cas/mathstat/People/kalman/pdffiles/mmgautodiff.pdf), + * Mathematics Magazine, vol. 75, no. 3, June 2002. Rall's numbers are an extension to the real numbers used + * throughout mathematical expressions; they hold the derivative together with the value of a function. Dan Kalman's + * derivative structures hold all partial derivatives up to any specified order, with respect to any number of free + * parameters. Rall's numbers therefore can be seen as derivative structures for order one derivative and one free + * parameter, and real numbers can be seen as derivative structures with zero order derivative and no free parameters. + * + * Derived from + * [Commons Math's `DerivativeStructure`](https://github.com/apache/commons-math/blob/924f6c357465b39beb50e3c916d5eb6662194175/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/analysis/differentiation/DerivativeStructure.java). + */ +@UnstableKMathAPI +public interface DS> { + public val derivativeAlgebra: DSAlgebra + public val data: Buffer +} + +/** + * Get a partial derivative. + * + * @param orders derivation orders with respect to each variable (if all orders are 0, the value is returned). + * @return partial derivative. + * @see value + */ +@UnstableKMathAPI +public fun > DS.getPartialDerivative(vararg orders: Int): T = + data[derivativeAlgebra.compiler.getPartialDerivativeIndex(*orders)] + +/** + * The value part of the derivative structure. + * + * @see getPartialDerivative + */ +@UnstableKMathAPI +public val > DS.value: T get() = data[0] + +@UnstableKMathAPI +public abstract class DSAlgebra>( + public val algebra: A, + public val bufferFactory: MutableBufferFactory, + public val order: Int, + bindings: Map, +) : ExpressionAlgebra> { + + @OptIn(UnstableKMathAPI::class) + private fun bufferForVariable(index: Int, value: T): Buffer { + val buffer = bufferFactory(compiler.size) { algebra.zero } + buffer[0] = value + if (compiler.order > 0) { + // the derivative of the variable with respect to itself is 1. + + val indexOfDerivative = compiler.getPartialDerivativeIndex(*IntArray(numberOfVariables).apply { + set(index, 1) + }) + + buffer[indexOfDerivative] = algebra.one + } + return buffer + } + + @UnstableKMathAPI + protected inner class DSImpl internal constructor( + override val data: Buffer, + ) : DS { + override val derivativeAlgebra: DSAlgebra get() = this@DSAlgebra + } + + protected fun DS(data: Buffer): DS = DSImpl(data) + + + /** + * Build an instance representing a variable. + * + * Instances built using this constructor are considered to be the free variables with respect to which + * differentials are computed. As such, their differential with respect to themselves is +1. + */ + public fun variable( + index: Int, + value: T, + ): DS { + require(index < compiler.freeParameters) { "number is too large: $index >= ${compiler.freeParameters}" } + return DS(bufferForVariable(index, value)) + } + + /** + * Build an instance from all its derivatives. + * + * @param derivatives derivatives sorted according to [DSCompiler.getPartialDerivativeIndex]. + */ + public fun ofDerivatives( + vararg derivatives: T, + ): DS { + require(derivatives.size == compiler.size) { "dimension mismatch: ${derivatives.size} and ${compiler.size}" } + val data = derivatives.asBuffer() + + return DS(data) + } + + /** + * A class implementing both [DS] and [Symbol]. + */ + @UnstableKMathAPI + public inner class DSSymbol internal constructor( + index: Int, + symbol: Symbol, + value: T, + ) : Symbol by symbol, DS { + override val derivativeAlgebra: DSAlgebra get() = this@DSAlgebra + override val data: Buffer = bufferForVariable(index, value) + } + + + public val numberOfVariables: Int = bindings.size + + /** + * Get the compiler for number of free parameters and order. + * + * @return cached rules set. + */ + @PublishedApi + internal val compiler: DSCompiler by lazy { + // get the cached compilers + val cache: Array?>>? = null + + // we need to create more compilers + val maxParameters: Int = max(numberOfVariables, cache?.size ?: 0) + val maxOrder: Int = max(order, if (cache == null) 0 else cache[0].size) + val newCache: Array?>> = Array(maxParameters + 1) { arrayOfNulls(maxOrder + 1) } + + if (cache != null) { + // preserve the already created compilers + for (i in cache.indices) { + cache[i].copyInto(newCache[i], endIndex = cache[i].size) + } + } + + // create the array in increasing diagonal order + for (diag in 0..numberOfVariables + order) { + for (o in max(0, diag - numberOfVariables)..min(order, diag)) { + val p: Int = diag - o + if (newCache[p][o] == null) { + val valueCompiler: DSCompiler? = if (p == 0) null else newCache[p - 1][o]!! + val derivativeCompiler: DSCompiler? = if (o == 0) null else newCache[p][o - 1]!! + + newCache[p][o] = DSCompiler( + algebra, + bufferFactory, + p, + o, + valueCompiler, + derivativeCompiler, + ) + } + } + } + + return@lazy newCache[numberOfVariables][order]!! + } + + private val variables: Map = bindings.entries.mapIndexed { index, (key, value) -> + key to DSSymbol( + index, + key, + value, + ) + }.toMap() + + + public override fun const(value: T): DS { + val buffer = bufferFactory(compiler.size) { algebra.zero } + buffer[0] = value + + return DS(buffer) + } + + override fun bindSymbolOrNull(value: String): DSSymbol? = variables[StringSymbol(value)] + + override fun bindSymbol(value: String): DSSymbol = + bindSymbolOrNull(value) ?: error("Symbol '$value' is not supported in $this") + + public fun bindSymbolOrNull(symbol: Symbol): DSSymbol? = variables[symbol.identity] + + public fun bindSymbol(symbol: Symbol): DSSymbol = + bindSymbolOrNull(symbol.identity) ?: error("Symbol '${symbol}' is not supported in $this") + + public fun DS.derivative(symbols: List): T { + require(symbols.size <= order) { "The order of derivative ${symbols.size} exceeds computed order $order" } + val ordersCount = symbols.groupBy { it }.mapValues { it.value.size } + return getPartialDerivative(*variables.keys.map { ordersCount[it] ?: 0 }.toIntArray()) + } + + public fun DS.derivative(vararg symbols: Symbol): T = derivative(symbols.toList()) + +} + + +/** + * A ring over [DS]. + * + * @property order The derivation order. + * @param bindings The map of bindings values. All bindings are considered free parameters. + */ +@UnstableKMathAPI +public open class DSRing( + algebra: A, + bufferFactory: MutableBufferFactory, + order: Int, + bindings: Map, +) : DSAlgebra(algebra, bufferFactory, order, bindings), + Ring>, ScaleOperations>, + NumericAlgebra>, + NumbersAddOps> where A : Ring, A : NumericAlgebra, A : ScaleOperations { + + override fun bindSymbolOrNull(value: String): DSSymbol? = + super.bindSymbolOrNull(value) + + override fun DS.unaryMinus(): DS = mapData { -it } + + /** + * Create a copy of given [Buffer] and modify it according to [block] + */ + protected inline fun DS.transformDataBuffer(block: A.(MutableBuffer) -> Unit): DS { + require(derivativeAlgebra == this@DSRing) { "All derivative operations should be done in the same algebra" } + val newData = bufferFactory(compiler.size) { data[it] } + algebra.block(newData) + return DS(newData) + } + + protected fun DS.mapData(block: A.(T) -> T): DS { + require(derivativeAlgebra == this@DSRing) { "All derivative operations should be done in the same algebra" } + val newData: Buffer = data.map(bufferFactory) { + algebra.block(it) + } + return DS(newData) + } + + protected fun DS.mapDataIndexed(block: (Int, T) -> T): DS { + require(derivativeAlgebra == this@DSRing) { "All derivative operations should be done in the same algebra" } + val newData: Buffer = data.mapIndexed(bufferFactory, block) + return DS(newData) + } + + override val zero: DS by lazy { + const(algebra.zero) + } + + override val one: DS by lazy { + const(algebra.one) + } + + override fun number(value: Number): DS = const(algebra.number(value)) + + override fun add(left: DS, right: DS): DS = left.transformDataBuffer { result -> + require(right.derivativeAlgebra == this@DSRing) { "All derivative operations should be done in the same algebra" } + compiler.add(left.data, 0, right.data, 0, result, 0) + } + + override fun scale(a: DS, value: Double): DS = a.mapData { + it.times(value) + } + + override fun multiply( + left: DS, + right: DS, + ): DS = left.transformDataBuffer { result -> + compiler.multiply(left.data, 0, right.data, 0, result, 0) + } +// +// override fun DS.minus(arg: DS): DS = transformDataBuffer { result -> +// subtract(data, 0, arg.data, 0, result, 0) +// } + + override operator fun DS.plus(other: Number): DS = transformDataBuffer { + it[0] += number(other) + } + +// +// override operator fun DS.minus(other: Number): DS = +// this + (-other.toDouble()) + + override operator fun Number.plus(other: DS): DS = other + this + override operator fun Number.minus(other: DS): DS = other - this +} + +@UnstableKMathAPI +public class DerivativeStructureRingExpression( + public val algebra: A, + public val bufferFactory: MutableBufferFactory, + public val function: DSRing.() -> DS, +) : DifferentiableExpression where A : Ring, A : ScaleOperations, A : NumericAlgebra { + override operator fun invoke(arguments: Map): T = + DSRing(algebra, bufferFactory, 0, arguments).function().value + + override fun derivativeOrNull(symbols: List): Expression = Expression { arguments -> + with( + DSRing( + algebra, + bufferFactory, + symbols.size, + arguments + ) + ) { function().derivative(symbols) } + } +} + +/** + * A field over commons-math [DerivativeStructure]. + * + * @property order The derivation order. + * @param bindings The map of bindings values. All bindings are considered free parameters. + */ +@UnstableKMathAPI +public class DSField>( + algebra: A, + bufferFactory: MutableBufferFactory, + order: Int, + bindings: Map, +) : DSRing(algebra, bufferFactory, order, bindings), ExtendedField> { + override fun number(value: Number): DS = const(algebra.number(value)) + + override fun divide(left: DS, right: DS): DS = left.transformDataBuffer { result -> + compiler.divide(left.data, 0, right.data, 0, result, 0) + } + + override fun sin(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.sin(arg.data, 0, result, 0) + } + + override fun cos(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.cos(arg.data, 0, result, 0) + } + + override fun tan(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.tan(arg.data, 0, result, 0) + } + + override fun asin(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.asin(arg.data, 0, result, 0) + } + + override fun acos(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.acos(arg.data, 0, result, 0) + } + + override fun atan(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.atan(arg.data, 0, result, 0) + } + + override fun sinh(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.sinh(arg.data, 0, result, 0) + } + + override fun cosh(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.cosh(arg.data, 0, result, 0) + } + + override fun tanh(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.tanh(arg.data, 0, result, 0) + } + + override fun asinh(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.asinh(arg.data, 0, result, 0) + } + + override fun acosh(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.acosh(arg.data, 0, result, 0) + } + + override fun atanh(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.atanh(arg.data, 0, result, 0) + } + + override fun power(arg: DS, pow: Number): DS = when (pow) { + is Int -> arg.transformDataBuffer { result -> + compiler.pow(arg.data, 0, pow, result, 0) + } + else -> arg.transformDataBuffer { result -> + compiler.pow(arg.data, 0, pow.toDouble(), result, 0) + } + } + + override fun sqrt(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.sqrt(arg.data, 0, result, 0) + } + + public fun power(arg: DS, pow: DS): DS = arg.transformDataBuffer { result -> + compiler.pow(arg.data, 0, pow.data, 0, result, 0) + } + + override fun exp(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.exp(arg.data, 0, result, 0) + } + + override fun ln(arg: DS): DS = arg.transformDataBuffer { result -> + compiler.ln(arg.data, 0, result, 0) + } +} + +@UnstableKMathAPI +public class DerivativeStructureFieldExpression>( + public val algebra: A, + public val bufferFactory: MutableBufferFactory, + public val function: DSField.() -> DS, +) : DifferentiableExpression { + override operator fun invoke(arguments: Map): T = + DSField(algebra, bufferFactory, 0, arguments).function().value + + override fun derivativeOrNull(symbols: List): Expression = Expression { arguments -> + DSField( + algebra, + bufferFactory, + symbols.size, + arguments, + ).run { function().derivative(symbols) } + } +} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DerivativeStructure.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DerivativeStructure.kt deleted file mode 100644 index 01c045cdb..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DerivativeStructure.kt +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. - */ - -package space.kscience.kmath.expressions - -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.asBuffer - -/** - * Class representing both the value and the differentials of a function. - * - * This class is the workhorse of the differentiation package. - * - * This class is an implementation of the extension to Rall's numbers described in Dan Kalman's paper [Doubly Recursive - * Multivariate Automatic Differentiation](http://www1.american.edu/cas/mathstat/People/kalman/pdffiles/mmgautodiff.pdf), - * Mathematics Magazine, vol. 75, no. 3, June 2002. Rall's numbers are an extension to the real numbers used - * throughout mathematical expressions; they hold the derivative together with the value of a function. Dan Kalman's - * derivative structures hold all partial derivatives up to any specified order, with respect to any number of free - * parameters. Rall's numbers therefore can be seen as derivative structures for order one derivative and one free - * parameter, and real numbers can be seen as derivative structures with zero order derivative and no free parameters. - * - * Derived from - * [Commons Math's `DerivativeStructure`](https://github.com/apache/commons-math/blob/924f6c357465b39beb50e3c916d5eb6662194175/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/analysis/differentiation/DerivativeStructure.java). - */ -@UnstableKMathAPI -public open class DerivativeStructure> @PublishedApi internal constructor( - private val derivativeAlgebra: DerivativeStructureAlgebra, - @PublishedApi internal val data: Buffer, -) { - - public val compiler: DSCompiler get() = derivativeAlgebra.compiler - - /** - * The number of free parameters. - */ - public val freeParameters: Int get() = compiler.freeParameters - - /** - * The derivation order. - */ - public val order: Int get() = compiler.order - - /** - * The value part of the derivative structure. - * - * @see getPartialDerivative - */ - public val value: T get() = data[0] - - /** - * Get a partial derivative. - * - * @param orders derivation orders with respect to each variable (if all orders are 0, the value is returned). - * @return partial derivative. - * @see value - */ - public fun getPartialDerivative(vararg orders: Int): T = data[compiler.getPartialDerivativeIndex(*orders)] - - - /** - * Test for the equality of two derivative structures. - * - * Derivative structures are considered equal if they have the same number - * of free parameters, the same derivation order, and the same derivatives. - * - * @return `true` if two derivative structures are equal. - */ - public override fun equals(other: Any?): Boolean { - if (this === other) return true - - if (other is DerivativeStructure<*, *>) { - return ((freeParameters == other.freeParameters) && - (order == other.order) && - data == other.data) - } - - return false - } - - public override fun hashCode(): Int = - 227 + 229 * freeParameters + 233 * order + 239 * data.hashCode() - - public companion object { - - /** - * Build an instance representing a variable. - * - * Instances built using this constructor are considered to be the free variables with respect to which - * differentials are computed. As such, their differential with respect to themselves is +1. - */ - public fun > variable( - derivativeAlgebra: DerivativeStructureAlgebra, - index: Int, - value: T, - ): DerivativeStructure { - val compiler = derivativeAlgebra.compiler - require(index < compiler.freeParameters) { "number is too large: $index >= ${compiler.freeParameters}" } - return DerivativeStructure(derivativeAlgebra, derivativeAlgebra.bufferForVariable(index, value)) - } - - /** - * Build an instance from all its derivatives. - * - * @param derivatives derivatives sorted according to [DSCompiler.getPartialDerivativeIndex]. - */ - public fun > ofDerivatives( - derivativeAlgebra: DerivativeStructureAlgebra, - vararg derivatives: T, - ): DerivativeStructure { - val compiler = derivativeAlgebra.compiler - require(derivatives.size == compiler.size) { "dimension mismatch: ${derivatives.size} and ${compiler.size}" } - val data = derivatives.asBuffer() - - return DerivativeStructure( - derivativeAlgebra, - data - ) - } - } -} - -@OptIn(UnstableKMathAPI::class) -private fun > DerivativeStructureAlgebra.bufferForVariable(index: Int, value: T): Buffer { - val buffer = bufferFactory(compiler.size) { algebra.zero } - buffer[0] = value - if (compiler.order > 0) { - // the derivative of the variable with respect to itself is 1. - - val indexOfDerivative = compiler.getPartialDerivativeIndex(*IntArray(numberOfVariables).apply { - set(index, 1) - }) - - buffer[indexOfDerivative] = algebra.one - } - return buffer -} - -/** - * A class implementing both [DerivativeStructure] and [Symbol]. - */ -@UnstableKMathAPI -public class DerivativeStructureSymbol> internal constructor( - derivativeAlgebra: DerivativeStructureAlgebra, - index: Int, - symbol: Symbol, - value: T, -) : Symbol by symbol, DerivativeStructure( - derivativeAlgebra, derivativeAlgebra.bufferForVariable(index, value) -) { - override fun toString(): String = symbol.toString() - override fun equals(other: Any?): Boolean = (other as? Symbol) == symbol - override fun hashCode(): Int = symbol.hashCode() -} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpression.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpression.kt deleted file mode 100644 index 638057921..000000000 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpression.kt +++ /dev/null @@ -1,349 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. - */ - -package space.kscience.kmath.expressions - -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.operations.* -import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.MutableBuffer -import space.kscience.kmath.structures.MutableBufferFactory -import kotlin.math.max -import kotlin.math.min - -@UnstableKMathAPI -public abstract class DerivativeStructureAlgebra>( - public val algebra: A, - public val bufferFactory: MutableBufferFactory, - public val order: Int, - bindings: Map, -) : ExpressionAlgebra> { - - public val numberOfVariables: Int = bindings.size - - - /** - * Get the compiler for number of free parameters and order. - * - * @return cached rules set. - */ - @PublishedApi - internal val compiler: DSCompiler by lazy { - // get the cached compilers - val cache: Array?>>? = null - - // we need to create more compilers - val maxParameters: Int = max(numberOfVariables, cache?.size ?: 0) - val maxOrder: Int = max(order, if (cache == null) 0 else cache[0].size) - val newCache: Array?>> = Array(maxParameters + 1) { arrayOfNulls(maxOrder + 1) } - - if (cache != null) { - // preserve the already created compilers - for (i in cache.indices) { - cache[i].copyInto(newCache[i], endIndex = cache[i].size) - } - } - - // create the array in increasing diagonal order - for (diag in 0..numberOfVariables + order) { - for (o in max(0, diag - numberOfVariables)..min(order, diag)) { - val p: Int = diag - o - if (newCache[p][o] == null) { - val valueCompiler: DSCompiler? = if (p == 0) null else newCache[p - 1][o]!! - val derivativeCompiler: DSCompiler? = if (o == 0) null else newCache[p][o - 1]!! - - newCache[p][o] = DSCompiler( - algebra, - bufferFactory, - p, - o, - valueCompiler, - derivativeCompiler, - ) - } - } - } - - return@lazy newCache[numberOfVariables][order]!! - } - - private val variables: Map> = - bindings.entries.mapIndexed { index, (key, value) -> - key to DerivativeStructureSymbol( - this, - index, - key, - value, - ) - }.toMap() - - - - public override fun const(value: T): DerivativeStructure { - val buffer = bufferFactory(compiler.size) { algebra.zero } - buffer[0] = value - - return DerivativeStructure( - this, - buffer - ) - } - - override fun bindSymbolOrNull(value: String): DerivativeStructureSymbol? = variables[StringSymbol(value)] - - override fun bindSymbol(value: String): DerivativeStructureSymbol = - bindSymbolOrNull(value) ?: error("Symbol '$value' is not supported in $this") - - public fun bindSymbolOrNull(symbol: Symbol): DerivativeStructureSymbol? = variables[symbol.identity] - - public fun bindSymbol(symbol: Symbol): DerivativeStructureSymbol = - bindSymbolOrNull(symbol.identity) ?: error("Symbol '${symbol}' is not supported in $this") - - public fun DerivativeStructure.derivative(symbols: List): T { - require(symbols.size <= order) { "The order of derivative ${symbols.size} exceeds computed order $order" } - val ordersCount = symbols.groupBy { it }.mapValues { it.value.size } - return getPartialDerivative(*variables.keys.map { ordersCount[it] ?: 0 }.toIntArray()) - } - - public fun DerivativeStructure.derivative(vararg symbols: Symbol): T = derivative(symbols.toList()) - -} - - -/** - * A ring over [DerivativeStructure]. - * - * @property order The derivation order. - * @param bindings The map of bindings values. All bindings are considered free parameters. - */ -@UnstableKMathAPI -public open class DerivativeStructureRing( - algebra: A, - bufferFactory: MutableBufferFactory, - order: Int, - bindings: Map, -) : DerivativeStructureAlgebra(algebra, bufferFactory, order, bindings), - Ring>, ScaleOperations>, - NumericAlgebra>, - NumbersAddOps> where A : Ring, A : NumericAlgebra, A : ScaleOperations { - - override fun bindSymbolOrNull(value: String): DerivativeStructureSymbol? = - super.bindSymbolOrNull(value) - - override fun DerivativeStructure.unaryMinus(): DerivativeStructure { - val newData = algebra { data.map(bufferFactory) { -it } } - return DerivativeStructure(this@DerivativeStructureRing, newData) - } - - /** - * Create a copy of given [Buffer] and modify it according to [block] - */ - protected inline fun DerivativeStructure.transformDataBuffer(block: DSCompiler.(MutableBuffer) -> Unit): DerivativeStructure { - val newData = bufferFactory(compiler.size) { data[it] } - compiler.block(newData) - return DerivativeStructure(this@DerivativeStructureRing, newData) - } - - protected fun DerivativeStructure.mapData(block: (T) -> T): DerivativeStructure { - val newData: Buffer = data.map(bufferFactory, block) - return DerivativeStructure(this@DerivativeStructureRing, newData) - } - - protected fun DerivativeStructure.mapDataIndexed(block: (Int, T) -> T): DerivativeStructure { - val newData: Buffer = data.mapIndexed(bufferFactory, block) - return DerivativeStructure(this@DerivativeStructureRing, newData) - } - - override val zero: DerivativeStructure by lazy { - const(algebra.zero) - } - - override val one: DerivativeStructure by lazy { - const(algebra.one) - } - - override fun number(value: Number): DerivativeStructure = const(algebra.number(value)) - - override fun add(left: DerivativeStructure, right: DerivativeStructure): DerivativeStructure { - left.compiler.checkCompatibility(right.compiler) - return left.transformDataBuffer { result -> - add(left.data, 0, right.data, 0, result, 0) - } - } - - override fun scale(a: DerivativeStructure, value: Double): DerivativeStructure = algebra { - a.mapData { it.times(value) } - } - - override fun multiply( - left: DerivativeStructure, - right: DerivativeStructure, - ): DerivativeStructure { - left.compiler.checkCompatibility(right.compiler) - return left.transformDataBuffer { result -> - multiply(left.data, 0, right.data, 0, result, 0) - } - } - - override fun DerivativeStructure.minus(arg: DerivativeStructure): DerivativeStructure { - compiler.checkCompatibility(arg.compiler) - return transformDataBuffer { result -> - subtract(data, 0, arg.data, 0, result, 0) - } - } - - override operator fun DerivativeStructure.plus(other: Number): DerivativeStructure = algebra { - transformDataBuffer { - it[0] += number(other) - } - } - - override operator fun DerivativeStructure.minus(other: Number): DerivativeStructure = - this + (-other.toDouble()) - - override operator fun Number.plus(other: DerivativeStructure): DerivativeStructure = other + this - override operator fun Number.minus(other: DerivativeStructure): DerivativeStructure = other - this -} - -@UnstableKMathAPI -public class DerivativeStructureRingExpression( - public val algebra: A, - public val bufferFactory: MutableBufferFactory, - public val function: DerivativeStructureRing.() -> DerivativeStructure, -) : DifferentiableExpression where A : Ring, A : ScaleOperations, A : NumericAlgebra { - override operator fun invoke(arguments: Map): T = - DerivativeStructureRing(algebra, bufferFactory, 0, arguments).function().value - - override fun derivativeOrNull(symbols: List): Expression = Expression { arguments -> - with( - DerivativeStructureRing( - algebra, - bufferFactory, - symbols.size, - arguments - ) - ) { function().derivative(symbols) } - } -} - -/** - * A field over commons-math [DerivativeStructure]. - * - * @property order The derivation order. - * @param bindings The map of bindings values. All bindings are considered free parameters. - */ -@UnstableKMathAPI -public class DerivativeStructureField>( - algebra: A, - bufferFactory: MutableBufferFactory, - order: Int, - bindings: Map, -) : DerivativeStructureRing(algebra, bufferFactory, order, bindings), ExtendedField> { - override fun number(value: Number): DerivativeStructure = const(algebra.number(value)) - - override fun divide(left: DerivativeStructure, right: DerivativeStructure): DerivativeStructure { - left.compiler.checkCompatibility(right.compiler) - return left.transformDataBuffer { result -> - left.compiler.divide(left.data, 0, right.data, 0, result, 0) - } - } - - override fun sin(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> - sin(arg.data, 0, result, 0) - } - - override fun cos(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> - cos(arg.data, 0, result, 0) - } - - override fun tan(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> - tan(arg.data, 0, result, 0) - } - - override fun asin(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> - asin(arg.data, 0, result, 0) - } - - override fun acos(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> - acos(arg.data, 0, result, 0) - } - - override fun atan(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> - atan(arg.data, 0, result, 0) - } - - override fun sinh(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> - sinh(arg.data, 0, result, 0) - } - - override fun cosh(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> - cosh(arg.data, 0, result, 0) - } - - override fun tanh(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> - tanh(arg.data, 0, result, 0) - } - - override fun asinh(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> - asinh(arg.data, 0, result, 0) - } - - override fun acosh(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> - acosh(arg.data, 0, result, 0) - } - - override fun atanh(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> - atanh(arg.data, 0, result, 0) - } - - override fun power(arg: DerivativeStructure, pow: Number): DerivativeStructure = when (pow) { - is Int -> arg.transformDataBuffer { result -> - pow(arg.data, 0, pow, result, 0) - } - else -> arg.transformDataBuffer { result -> - pow(arg.data, 0, pow.toDouble(), result, 0) - } - } - - override fun sqrt(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> - sqrt(arg.data, 0, result, 0) - } - - public fun power(arg: DerivativeStructure, pow: DerivativeStructure): DerivativeStructure { - arg.compiler.checkCompatibility(pow.compiler) - return arg.transformDataBuffer { result -> - pow(arg.data, 0, pow.data, 0, result, 0) - } - } - - override fun exp(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> - exp(arg.data, 0, result, 0) - } - - override fun ln(arg: DerivativeStructure): DerivativeStructure = arg.transformDataBuffer { result -> - ln(arg.data, 0, result, 0) - } -} - -@UnstableKMathAPI -public class DerivativeStructureFieldExpression>( - public val algebra: A, - public val bufferFactory: MutableBufferFactory, - public val function: DerivativeStructureField.() -> DerivativeStructure, -) : DifferentiableExpression { - override operator fun invoke(arguments: Map): T = - DerivativeStructureField(algebra, bufferFactory, 0, arguments).function().value - - override fun derivativeOrNull(symbols: List): Expression = Expression { arguments -> - with( - DerivativeStructureField( - algebra, - bufferFactory, - symbols.size, - arguments, - ) - ) { function().derivative(symbols) } - } -} diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpressionTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpressionTest.kt index 429fe310b..fdeda4512 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpressionTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpressionTest.kt @@ -19,10 +19,10 @@ import kotlin.test.assertFails internal inline fun diff( order: Int, vararg parameters: Pair, - block: DerivativeStructureField.() -> Unit, + block: DSField.() -> Unit, ) { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - DerivativeStructureField(DoubleField, ::DoubleBuffer, order, mapOf(*parameters)).block() + DSField(DoubleField, ::DoubleBuffer, order, mapOf(*parameters)).block() } internal class AutoDiffTest { -- 2.34.1 From 846a6d2620810dc9e15538befba437f0882a77db Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 15 Jul 2022 17:20:00 +0300 Subject: [PATCH 133/275] Grand derivative refactoring. Phase 3 --- .../kscience/kmath/expressions/DSAlgebra.kt | 143 ++++++++++-------- .../kscience/kmath/expressions/DSCompiler.kt | 28 ++-- 2 files changed, 96 insertions(+), 75 deletions(-) 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 d9fc46b47..506fbd001 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 @@ -44,9 +44,29 @@ public interface DS> { * @see value */ @UnstableKMathAPI -public fun > DS.getPartialDerivative(vararg orders: Int): T = +private fun > DS.getPartialDerivative(vararg orders: Int): T = data[derivativeAlgebra.compiler.getPartialDerivativeIndex(*orders)] +/** + * Provide a partial derivative with given symbols. On symbol could me mentioned multiple times + */ +@UnstableKMathAPI +public fun > DS.derivative(symbols: List): T { + require(symbols.size <= derivativeAlgebra.order) { "The order of derivative ${symbols.size} exceeds computed order ${derivativeAlgebra.order}" } + val ordersCount: Map = symbols.map { it.identity }.groupBy { it }.mapValues { it.value.size } + return getPartialDerivative(*symbols.map { ordersCount[it] ?: 0 }.toIntArray()) +} + +/** + * Provide a partial derivative with given symbols. On symbol could me mentioned multiple times + */ +@UnstableKMathAPI +public fun > DS.derivative(vararg symbols: Symbol): T { + require(symbols.size <= derivativeAlgebra.order) { "The order of derivative ${symbols.size} exceeds computed order ${derivativeAlgebra.order}" } + val ordersCount: Map = symbols.map { it.identity }.groupBy { it }.mapValues { it.value.size } + return getPartialDerivative(*symbols.map { ordersCount[it] ?: 0 }.toIntArray()) +} + /** * The value part of the derivative structure. * @@ -61,9 +81,67 @@ public abstract class DSAlgebra>( public val bufferFactory: MutableBufferFactory, public val order: Int, bindings: Map, -) : ExpressionAlgebra> { +) : ExpressionAlgebra>, SymbolIndexer { + + /** + * Get the compiler for number of free parameters and order. + * + * @return cached rules set. + */ + @PublishedApi + internal val compiler: DSCompiler by lazy { + // get the cached compilers + val cache: Array?>>? = null + + // we need to create more compilers + val maxParameters: Int = max(numberOfVariables, cache?.size ?: 0) + val maxOrder: Int = max(order, if (cache == null) 0 else cache[0].size) + val newCache: Array?>> = Array(maxParameters + 1) { arrayOfNulls(maxOrder + 1) } + + if (cache != null) { + // preserve the already created compilers + for (i in cache.indices) { + cache[i].copyInto(newCache[i], endIndex = cache[i].size) + } + } + + // create the array in increasing diagonal order + for (diag in 0..numberOfVariables + order) { + for (o in max(0, diag - numberOfVariables)..min(order, diag)) { + val p: Int = diag - o + if (newCache[p][o] == null) { + val valueCompiler: DSCompiler? = if (p == 0) null else newCache[p - 1][o]!! + val derivativeCompiler: DSCompiler? = if (o == 0) null else newCache[p][o - 1]!! + + newCache[p][o] = DSCompiler( + algebra, + bufferFactory, + p, + o, + valueCompiler, + derivativeCompiler, + ) + } + } + } + + return@lazy newCache[numberOfVariables][order]!! + } + + private val variables: Map by lazy { + bindings.entries.mapIndexed { index, (key, value) -> + key to DSSymbol( + index, + key, + value, + ) + }.toMap() + } + override val symbols: List = bindings.map { it.key } + + public val numberOfVariables: Int get() = symbols.size + - @OptIn(UnstableKMathAPI::class) private fun bufferForVariable(index: Int, value: T): Buffer { val buffer = bufferFactory(compiler.size) { algebra.zero } buffer[0] = value @@ -80,7 +158,7 @@ public abstract class DSAlgebra>( } @UnstableKMathAPI - protected inner class DSImpl internal constructor( + private inner class DSImpl( override val data: Buffer, ) : DS { override val derivativeAlgebra: DSAlgebra get() = this@DSAlgebra @@ -130,63 +208,6 @@ public abstract class DSAlgebra>( override val data: Buffer = bufferForVariable(index, value) } - - public val numberOfVariables: Int = bindings.size - - /** - * Get the compiler for number of free parameters and order. - * - * @return cached rules set. - */ - @PublishedApi - internal val compiler: DSCompiler by lazy { - // get the cached compilers - val cache: Array?>>? = null - - // we need to create more compilers - val maxParameters: Int = max(numberOfVariables, cache?.size ?: 0) - val maxOrder: Int = max(order, if (cache == null) 0 else cache[0].size) - val newCache: Array?>> = Array(maxParameters + 1) { arrayOfNulls(maxOrder + 1) } - - if (cache != null) { - // preserve the already created compilers - for (i in cache.indices) { - cache[i].copyInto(newCache[i], endIndex = cache[i].size) - } - } - - // create the array in increasing diagonal order - for (diag in 0..numberOfVariables + order) { - for (o in max(0, diag - numberOfVariables)..min(order, diag)) { - val p: Int = diag - o - if (newCache[p][o] == null) { - val valueCompiler: DSCompiler? = if (p == 0) null else newCache[p - 1][o]!! - val derivativeCompiler: DSCompiler? = if (o == 0) null else newCache[p][o - 1]!! - - newCache[p][o] = DSCompiler( - algebra, - bufferFactory, - p, - o, - valueCompiler, - derivativeCompiler, - ) - } - } - } - - return@lazy newCache[numberOfVariables][order]!! - } - - private val variables: Map = bindings.entries.mapIndexed { index, (key, value) -> - key to DSSymbol( - index, - key, - value, - ) - }.toMap() - - public override fun const(value: T): DS { val buffer = bufferFactory(compiler.size) { algebra.zero } buffer[0] = value 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 e0050cf03..b5b2988a3 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 @@ -52,20 +52,20 @@ internal fun MutableBuffer.fill(element: T, fromIndex: Int = 0, toIndex: * * @property freeParameters Number of free parameters. * @property order Derivation order. - * @see DerivativeStructure + * @see DS */ -class DSCompiler> internal constructor( - val algebra: A, - val bufferFactory: MutableBufferFactory, - val freeParameters: Int, - val order: Int, +public class DSCompiler> internal constructor( + public val algebra: A, + public val bufferFactory: MutableBufferFactory, + public val freeParameters: Int, + public val order: Int, valueCompiler: DSCompiler?, derivativeCompiler: DSCompiler?, ) { /** * Number of partial derivatives (including the single 0 order derivative element). */ - val sizes: Array by lazy { + public val sizes: Array by lazy { compileSizes( freeParameters, order, @@ -76,7 +76,7 @@ class DSCompiler> internal constructor( /** * Indirection array for partial derivatives. */ - val derivativesIndirection: Array by lazy { + internal val derivativesIndirection: Array by lazy { compileDerivativesIndirection( freeParameters, order, valueCompiler, derivativeCompiler, @@ -86,7 +86,7 @@ class DSCompiler> internal constructor( /** * Indirection array of the lower derivative elements. */ - val lowerIndirection: IntArray by lazy { + internal val lowerIndirection: IntArray by lazy { compileLowerIndirection( freeParameters, order, valueCompiler, derivativeCompiler, @@ -96,7 +96,7 @@ class DSCompiler> internal constructor( /** * Indirection arrays for multiplication. */ - val multIndirection: Array> by lazy { + internal val multIndirection: Array> by lazy { compileMultiplicationIndirection( freeParameters, order, valueCompiler, derivativeCompiler, lowerIndirection, @@ -106,7 +106,7 @@ class DSCompiler> internal constructor( /** * Indirection arrays for function composition. */ - val compositionIndirection: Array> by lazy { + internal val compositionIndirection: Array> by lazy { compileCompositionIndirection( freeParameters, order, valueCompiler, derivativeCompiler, @@ -120,7 +120,7 @@ class DSCompiler> internal constructor( * This number includes the single 0 order derivative element, which is * guaranteed to be stored in the first element of the array. */ - val size: Int get() = sizes[freeParameters][order] + public val size: Int get() = sizes[freeParameters][order] /** * Get the index of a partial derivative in the array. @@ -147,7 +147,7 @@ class DSCompiler> internal constructor( * @return index of the partial derivative. * @see getPartialDerivativeOrders */ - fun getPartialDerivativeIndex(vararg orders: Int): Int { + public fun getPartialDerivativeIndex(vararg orders: Int): Int { // safety check require(orders.size == freeParameters) { "dimension mismatch: ${orders.size} and $freeParameters" } return getPartialDerivativeIndex(freeParameters, order, sizes, *orders) @@ -162,7 +162,7 @@ class DSCompiler> internal constructor( * @return orders derivation orders with respect to each parameter * @see getPartialDerivativeIndex */ - fun getPartialDerivativeOrders(index: Int): IntArray = derivativesIndirection[index] + public fun getPartialDerivativeOrders(index: Int): IntArray = derivativesIndirection[index] } /** -- 2.34.1 From bfadf5b33d545ac0e4d40f2253e20e0ad88e4ba0 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 15 Jul 2022 17:31:28 +0300 Subject: [PATCH 134/275] Name refactor --- .../kotlin/space/kscience/kmath/expressions/DSAlgebra.kt | 2 +- .../kmath/expressions/DerivativeStructureExpressionTest.kt | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) 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 506fbd001..59e6f4f6f 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 @@ -439,7 +439,7 @@ public class DSField>( } @UnstableKMathAPI -public class DerivativeStructureFieldExpression>( +public class DSFieldExpression>( public val algebra: A, public val bufferFactory: MutableBufferFactory, public val function: DSField.() -> DS, diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpressionTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpressionTest.kt index fdeda4512..e5bc9805a 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpressionTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpressionTest.kt @@ -30,7 +30,7 @@ internal class AutoDiffTest { private val y by symbol @Test - fun derivativeStructureFieldTest() { + fun dsAlgebraTest() { diff(2, x to 1.0, y to 1.0) { val x = bindSymbol(x)//by binding() val y = bindSymbol("y") @@ -44,8 +44,8 @@ internal class AutoDiffTest { } @Test - fun autoDifTest() { - val f = DerivativeStructureFieldExpression(DoubleField, ::DoubleBuffer) { + fun dsExpressionTest() { + val f = DSFieldExpression(DoubleField, ::DoubleBuffer) { val x by binding val y by binding x.pow(2) + 2 * x * y + y.pow(2) + 1 -- 2.34.1 From 18ae964e57a2d1059aaa4f17909da45c3a4a1972 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 15 Jul 2022 17:35:13 +0300 Subject: [PATCH 135/275] Name refactor --- .../space/kscience/kmath/ejml/_generated.kt | 1003 +++++++++++++++++ 1 file changed, 1003 insertions(+) create mode 100644 kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt new file mode 100644 index 000000000..aac327a84 --- /dev/null +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt @@ -0,0 +1,1003 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + */ + +/* This file is generated with buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt */ + +package space.kscience.kmath.ejml + +import org.ejml.data.* +import org.ejml.dense.row.CommonOps_DDRM +import org.ejml.dense.row.CommonOps_FDRM +import org.ejml.dense.row.factory.DecompositionFactory_DDRM +import org.ejml.dense.row.factory.DecompositionFactory_FDRM +import org.ejml.sparse.FillReducing +import org.ejml.sparse.csc.CommonOps_DSCC +import org.ejml.sparse.csc.CommonOps_FSCC +import org.ejml.sparse.csc.factory.DecompositionFactory_DSCC +import org.ejml.sparse.csc.factory.DecompositionFactory_FSCC +import org.ejml.sparse.csc.factory.LinearSolverFactory_DSCC +import org.ejml.sparse.csc.factory.LinearSolverFactory_FSCC +import space.kscience.kmath.linear.* +import space.kscience.kmath.linear.Matrix +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.nd.StructureFeature +import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.FloatField +import space.kscience.kmath.operations.invoke +import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.structures.FloatBuffer +import kotlin.reflect.KClass +import kotlin.reflect.cast + +/** + * [EjmlVector] specialization for [Double]. + */ +public class EjmlDoubleVector(override val origin: M) : EjmlVector(origin) { + init { + require(origin.numRows == 1) { "The origin matrix must have only one row to form a vector" } + } + + override operator fun get(index: Int): Double = origin[0, index] +} + +/** + * [EjmlVector] specialization for [Float]. + */ +public class EjmlFloatVector(override val origin: M) : EjmlVector(origin) { + init { + require(origin.numRows == 1) { "The origin matrix must have only one row to form a vector" } + } + + override operator fun get(index: Int): Float = origin[0, index] +} + +/** + * [EjmlMatrix] specialization for [Double]. + */ +public class EjmlDoubleMatrix(override val origin: M) : EjmlMatrix(origin) { + override operator fun get(i: Int, j: Int): Double = origin[i, j] +} + +/** + * [EjmlMatrix] specialization for [Float]. + */ +public class EjmlFloatMatrix(override val origin: M) : EjmlMatrix(origin) { + override operator fun get(i: Int, j: Int): Float = origin[i, j] +} + +/** + * [EjmlLinearSpace] implementation based on [CommonOps_DDRM], [DecompositionFactory_DDRM] operations and + * [DMatrixRMaj] matrices. + */ +public object EjmlLinearSpaceDDRM : EjmlLinearSpace() { + /** + * The [DoubleField] reference. + */ + override val elementAlgebra: DoubleField get() = DoubleField + + @Suppress("UNCHECKED_CAST") + override fun Matrix.toEjml(): EjmlDoubleMatrix = when { + this is EjmlDoubleMatrix<*> && origin is DMatrixRMaj -> this as EjmlDoubleMatrix + else -> buildMatrix(rowNum, colNum) { i, j -> get(i, j) } + } + + @Suppress("UNCHECKED_CAST") + override fun Point.toEjml(): EjmlDoubleVector = when { + this is EjmlDoubleVector<*> && origin is DMatrixRMaj -> this as EjmlDoubleVector + else -> EjmlDoubleVector(DMatrixRMaj(size, 1).also { + (0 until it.numRows).forEach { row -> it[row, 0] = get(row) } + }) + } + + override fun buildMatrix( + rows: Int, + columns: Int, + initializer: DoubleField.(i: Int, j: Int) -> Double, + ): EjmlDoubleMatrix = DMatrixRMaj(rows, columns).also { + (0 until rows).forEach { row -> + (0 until columns).forEach { col -> it[row, col] = elementAlgebra.initializer(row, col) } + } + }.wrapMatrix() + + override fun buildVector( + size: Int, + initializer: DoubleField.(Int) -> Double, + ): EjmlDoubleVector = EjmlDoubleVector(DMatrixRMaj(size, 1).also { + (0 until it.numRows).forEach { row -> it[row, 0] = elementAlgebra.initializer(row) } + }) + + private fun T.wrapMatrix() = EjmlDoubleMatrix(this) + private fun T.wrapVector() = EjmlDoubleVector(this) + + override fun Matrix.unaryMinus(): Matrix = this * elementAlgebra { -one } + + override fun Matrix.dot(other: Matrix): EjmlDoubleMatrix { + val out = DMatrixRMaj(1, 1) + CommonOps_DDRM.mult(toEjml().origin, other.toEjml().origin, out) + return out.wrapMatrix() + } + + override fun Matrix.dot(vector: Point): EjmlDoubleVector { + val out = DMatrixRMaj(1, 1) + CommonOps_DDRM.mult(toEjml().origin, vector.toEjml().origin, out) + return out.wrapVector() + } + + override operator fun Matrix.minus(other: Matrix): EjmlDoubleMatrix { + val out = DMatrixRMaj(1, 1) + + CommonOps_DDRM.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra { -one }, + other.toEjml().origin, + out, + ) + + return out.wrapMatrix() + } + + override operator fun Matrix.times(value: Double): EjmlDoubleMatrix { + val res = DMatrixRMaj(1, 1) + CommonOps_DDRM.scale(value, toEjml().origin, res) + return res.wrapMatrix() + } + + override fun Point.unaryMinus(): EjmlDoubleVector { + val res = DMatrixRMaj(1, 1) + CommonOps_DDRM.changeSign(toEjml().origin, res) + return res.wrapVector() + } + + override fun Matrix.plus(other: Matrix): EjmlDoubleMatrix { + val out = DMatrixRMaj(1, 1) + + CommonOps_DDRM.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra.one, + other.toEjml().origin, + out, + ) + + return out.wrapMatrix() + } + + override fun Point.plus(other: Point): EjmlDoubleVector { + val out = DMatrixRMaj(1, 1) + + CommonOps_DDRM.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra.one, + other.toEjml().origin, + out, + ) + + return out.wrapVector() + } + + override fun Point.minus(other: Point): EjmlDoubleVector { + val out = DMatrixRMaj(1, 1) + + CommonOps_DDRM.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra { -one }, + other.toEjml().origin, + out, + ) + + return out.wrapVector() + } + + override fun Double.times(m: Matrix): EjmlDoubleMatrix = m * this + + override fun Point.times(value: Double): EjmlDoubleVector { + val res = DMatrixRMaj(1, 1) + CommonOps_DDRM.scale(value, toEjml().origin, res) + return res.wrapVector() + } + + override fun Double.times(v: Point): EjmlDoubleVector = v * this + + @UnstableKMathAPI + override fun computeFeature(structure: Matrix, type: KClass): F? { + structure.getFeature(type)?.let { return it } + val origin = structure.toEjml().origin + + return when (type) { + InverseMatrixFeature::class -> object : InverseMatrixFeature { + override val inverse: Matrix by lazy { + val res = origin.copy() + CommonOps_DDRM.invert(res) + res.wrapMatrix() + } + } + + DeterminantFeature::class -> object : DeterminantFeature { + override val determinant: Double by lazy { CommonOps_DDRM.det(origin) } + } + + SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature { + private val svd by lazy { + DecompositionFactory_DDRM.svd(origin.numRows, origin.numCols, true, true, false) + .apply { decompose(origin.copy()) } + } + + override val u: Matrix by lazy { svd.getU(null, false).wrapMatrix() } + override val s: Matrix by lazy { svd.getW(null).wrapMatrix() } + override val v: Matrix by lazy { svd.getV(null, false).wrapMatrix() } + override val singularValues: Point by lazy { DoubleBuffer(svd.singularValues) } + } + + QRDecompositionFeature::class -> object : QRDecompositionFeature { + private val qr by lazy { + DecompositionFactory_DDRM.qr().apply { decompose(origin.copy()) } + } + + override val q: Matrix by lazy { + qr.getQ(null, false).wrapMatrix().withFeature(OrthogonalFeature) + } + + override val r: Matrix by lazy { qr.getR(null, false).wrapMatrix().withFeature(UFeature) } + } + + CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature { + override val l: Matrix by lazy { + val cholesky = + DecompositionFactory_DDRM.chol(structure.rowNum, true).apply { decompose(origin.copy()) } + + cholesky.getT(null).wrapMatrix().withFeature(LFeature) + } + } + + LupDecompositionFeature::class -> object : LupDecompositionFeature { + private val lup by lazy { + DecompositionFactory_DDRM.lu(origin.numRows, origin.numCols).apply { decompose(origin.copy()) } + } + + override val l: Matrix by lazy { + lup.getLower(null).wrapMatrix().withFeature(LFeature) + } + + override val u: Matrix by lazy { + lup.getUpper(null).wrapMatrix().withFeature(UFeature) + } + + override val p: Matrix by lazy { lup.getRowPivot(null).wrapMatrix() } + } + + else -> null + }?.let{ + type.cast(it) + } + } + + /** + * Solves for *x* in the following equation: *x = [a] -1 · [b]*. + * + * @param a the base matrix. + * @param b n by p matrix. + * @return the solution for *x* that is n by p. + */ + public fun solve(a: Matrix, b: Matrix): EjmlDoubleMatrix { + val res = DMatrixRMaj(1, 1) + CommonOps_DDRM.solve(DMatrixRMaj(a.toEjml().origin), DMatrixRMaj(b.toEjml().origin), res) + return res.wrapMatrix() + } + + /** + * Solves for *x* in the following equation: *x = [a] -1 · [b]*. + * + * @param a the base matrix. + * @param b n by p vector. + * @return the solution for *x* that is n by p. + */ + public fun solve(a: Matrix, b: Point): EjmlDoubleVector { + val res = DMatrixRMaj(1, 1) + CommonOps_DDRM.solve(DMatrixRMaj(a.toEjml().origin), DMatrixRMaj(b.toEjml().origin), res) + return EjmlDoubleVector(res) + } +} + +/** + * [EjmlLinearSpace] implementation based on [CommonOps_FDRM], [DecompositionFactory_FDRM] operations and + * [FMatrixRMaj] matrices. + */ +public object EjmlLinearSpaceFDRM : EjmlLinearSpace() { + /** + * The [FloatField] reference. + */ + override val elementAlgebra: FloatField get() = FloatField + + @Suppress("UNCHECKED_CAST") + override fun Matrix.toEjml(): EjmlFloatMatrix = when { + this is EjmlFloatMatrix<*> && origin is FMatrixRMaj -> this as EjmlFloatMatrix + else -> buildMatrix(rowNum, colNum) { i, j -> get(i, j) } + } + + @Suppress("UNCHECKED_CAST") + override fun Point.toEjml(): EjmlFloatVector = when { + this is EjmlFloatVector<*> && origin is FMatrixRMaj -> this as EjmlFloatVector + else -> EjmlFloatVector(FMatrixRMaj(size, 1).also { + (0 until it.numRows).forEach { row -> it[row, 0] = get(row) } + }) + } + + override fun buildMatrix( + rows: Int, + columns: Int, + initializer: FloatField.(i: Int, j: Int) -> Float, + ): EjmlFloatMatrix = FMatrixRMaj(rows, columns).also { + (0 until rows).forEach { row -> + (0 until columns).forEach { col -> it[row, col] = elementAlgebra.initializer(row, col) } + } + }.wrapMatrix() + + override fun buildVector( + size: Int, + initializer: FloatField.(Int) -> Float, + ): EjmlFloatVector = EjmlFloatVector(FMatrixRMaj(size, 1).also { + (0 until it.numRows).forEach { row -> it[row, 0] = elementAlgebra.initializer(row) } + }) + + private fun T.wrapMatrix() = EjmlFloatMatrix(this) + private fun T.wrapVector() = EjmlFloatVector(this) + + override fun Matrix.unaryMinus(): Matrix = this * elementAlgebra { -one } + + override fun Matrix.dot(other: Matrix): EjmlFloatMatrix { + val out = FMatrixRMaj(1, 1) + CommonOps_FDRM.mult(toEjml().origin, other.toEjml().origin, out) + return out.wrapMatrix() + } + + override fun Matrix.dot(vector: Point): EjmlFloatVector { + val out = FMatrixRMaj(1, 1) + CommonOps_FDRM.mult(toEjml().origin, vector.toEjml().origin, out) + return out.wrapVector() + } + + override operator fun Matrix.minus(other: Matrix): EjmlFloatMatrix { + val out = FMatrixRMaj(1, 1) + + CommonOps_FDRM.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra { -one }, + other.toEjml().origin, + out, + ) + + return out.wrapMatrix() + } + + override operator fun Matrix.times(value: Float): EjmlFloatMatrix { + val res = FMatrixRMaj(1, 1) + CommonOps_FDRM.scale(value, toEjml().origin, res) + return res.wrapMatrix() + } + + override fun Point.unaryMinus(): EjmlFloatVector { + val res = FMatrixRMaj(1, 1) + CommonOps_FDRM.changeSign(toEjml().origin, res) + return res.wrapVector() + } + + override fun Matrix.plus(other: Matrix): EjmlFloatMatrix { + val out = FMatrixRMaj(1, 1) + + CommonOps_FDRM.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra.one, + other.toEjml().origin, + out, + ) + + return out.wrapMatrix() + } + + override fun Point.plus(other: Point): EjmlFloatVector { + val out = FMatrixRMaj(1, 1) + + CommonOps_FDRM.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra.one, + other.toEjml().origin, + out, + ) + + return out.wrapVector() + } + + override fun Point.minus(other: Point): EjmlFloatVector { + val out = FMatrixRMaj(1, 1) + + CommonOps_FDRM.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra { -one }, + other.toEjml().origin, + out, + ) + + return out.wrapVector() + } + + override fun Float.times(m: Matrix): EjmlFloatMatrix = m * this + + override fun Point.times(value: Float): EjmlFloatVector { + val res = FMatrixRMaj(1, 1) + CommonOps_FDRM.scale(value, toEjml().origin, res) + return res.wrapVector() + } + + override fun Float.times(v: Point): EjmlFloatVector = v * this + + @UnstableKMathAPI + override fun computeFeature(structure: Matrix, type: KClass): F? { + structure.getFeature(type)?.let { return it } + val origin = structure.toEjml().origin + + return when (type) { + InverseMatrixFeature::class -> object : InverseMatrixFeature { + override val inverse: Matrix by lazy { + val res = origin.copy() + CommonOps_FDRM.invert(res) + res.wrapMatrix() + } + } + + DeterminantFeature::class -> object : DeterminantFeature { + override val determinant: Float by lazy { CommonOps_FDRM.det(origin) } + } + + SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature { + private val svd by lazy { + DecompositionFactory_FDRM.svd(origin.numRows, origin.numCols, true, true, false) + .apply { decompose(origin.copy()) } + } + + override val u: Matrix by lazy { svd.getU(null, false).wrapMatrix() } + override val s: Matrix by lazy { svd.getW(null).wrapMatrix() } + override val v: Matrix by lazy { svd.getV(null, false).wrapMatrix() } + override val singularValues: Point by lazy { FloatBuffer(svd.singularValues) } + } + + QRDecompositionFeature::class -> object : QRDecompositionFeature { + private val qr by lazy { + DecompositionFactory_FDRM.qr().apply { decompose(origin.copy()) } + } + + override val q: Matrix by lazy { + qr.getQ(null, false).wrapMatrix().withFeature(OrthogonalFeature) + } + + override val r: Matrix by lazy { qr.getR(null, false).wrapMatrix().withFeature(UFeature) } + } + + CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature { + override val l: Matrix by lazy { + val cholesky = + DecompositionFactory_FDRM.chol(structure.rowNum, true).apply { decompose(origin.copy()) } + + cholesky.getT(null).wrapMatrix().withFeature(LFeature) + } + } + + LupDecompositionFeature::class -> object : LupDecompositionFeature { + private val lup by lazy { + DecompositionFactory_FDRM.lu(origin.numRows, origin.numCols).apply { decompose(origin.copy()) } + } + + override val l: Matrix by lazy { + lup.getLower(null).wrapMatrix().withFeature(LFeature) + } + + override val u: Matrix by lazy { + lup.getUpper(null).wrapMatrix().withFeature(UFeature) + } + + override val p: Matrix by lazy { lup.getRowPivot(null).wrapMatrix() } + } + + else -> null + }?.let{ + type.cast(it) + } + } + + /** + * Solves for *x* in the following equation: *x = [a] -1 · [b]*. + * + * @param a the base matrix. + * @param b n by p matrix. + * @return the solution for *x* that is n by p. + */ + public fun solve(a: Matrix, b: Matrix): EjmlFloatMatrix { + val res = FMatrixRMaj(1, 1) + CommonOps_FDRM.solve(FMatrixRMaj(a.toEjml().origin), FMatrixRMaj(b.toEjml().origin), res) + return res.wrapMatrix() + } + + /** + * Solves for *x* in the following equation: *x = [a] -1 · [b]*. + * + * @param a the base matrix. + * @param b n by p vector. + * @return the solution for *x* that is n by p. + */ + public fun solve(a: Matrix, b: Point): EjmlFloatVector { + val res = FMatrixRMaj(1, 1) + CommonOps_FDRM.solve(FMatrixRMaj(a.toEjml().origin), FMatrixRMaj(b.toEjml().origin), res) + return EjmlFloatVector(res) + } +} + +/** + * [EjmlLinearSpace] implementation based on [CommonOps_DSCC], [DecompositionFactory_DSCC] operations and + * [DMatrixSparseCSC] matrices. + */ +public object EjmlLinearSpaceDSCC : EjmlLinearSpace() { + /** + * The [DoubleField] reference. + */ + override val elementAlgebra: DoubleField get() = DoubleField + + @Suppress("UNCHECKED_CAST") + override fun Matrix.toEjml(): EjmlDoubleMatrix = when { + this is EjmlDoubleMatrix<*> && origin is DMatrixSparseCSC -> this as EjmlDoubleMatrix + else -> buildMatrix(rowNum, colNum) { i, j -> get(i, j) } + } + + @Suppress("UNCHECKED_CAST") + override fun Point.toEjml(): EjmlDoubleVector = when { + this is EjmlDoubleVector<*> && origin is DMatrixSparseCSC -> this as EjmlDoubleVector + else -> EjmlDoubleVector(DMatrixSparseCSC(size, 1).also { + (0 until it.numRows).forEach { row -> it[row, 0] = get(row) } + }) + } + + override fun buildMatrix( + rows: Int, + columns: Int, + initializer: DoubleField.(i: Int, j: Int) -> Double, + ): EjmlDoubleMatrix = DMatrixSparseCSC(rows, columns).also { + (0 until rows).forEach { row -> + (0 until columns).forEach { col -> it[row, col] = elementAlgebra.initializer(row, col) } + } + }.wrapMatrix() + + override fun buildVector( + size: Int, + initializer: DoubleField.(Int) -> Double, + ): EjmlDoubleVector = EjmlDoubleVector(DMatrixSparseCSC(size, 1).also { + (0 until it.numRows).forEach { row -> it[row, 0] = elementAlgebra.initializer(row) } + }) + + private fun T.wrapMatrix() = EjmlDoubleMatrix(this) + private fun T.wrapVector() = EjmlDoubleVector(this) + + override fun Matrix.unaryMinus(): Matrix = this * elementAlgebra { -one } + + override fun Matrix.dot(other: Matrix): EjmlDoubleMatrix { + val out = DMatrixSparseCSC(1, 1) + CommonOps_DSCC.mult(toEjml().origin, other.toEjml().origin, out) + return out.wrapMatrix() + } + + override fun Matrix.dot(vector: Point): EjmlDoubleVector { + val out = DMatrixSparseCSC(1, 1) + CommonOps_DSCC.mult(toEjml().origin, vector.toEjml().origin, out) + return out.wrapVector() + } + + override operator fun Matrix.minus(other: Matrix): EjmlDoubleMatrix { + val out = DMatrixSparseCSC(1, 1) + + CommonOps_DSCC.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra { -one }, + other.toEjml().origin, + out, + null, + null, + ) + + return out.wrapMatrix() + } + + override operator fun Matrix.times(value: Double): EjmlDoubleMatrix { + val res = DMatrixSparseCSC(1, 1) + CommonOps_DSCC.scale(value, toEjml().origin, res) + return res.wrapMatrix() + } + + override fun Point.unaryMinus(): EjmlDoubleVector { + val res = DMatrixSparseCSC(1, 1) + CommonOps_DSCC.changeSign(toEjml().origin, res) + return res.wrapVector() + } + + override fun Matrix.plus(other: Matrix): EjmlDoubleMatrix { + val out = DMatrixSparseCSC(1, 1) + + CommonOps_DSCC.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra.one, + other.toEjml().origin, + out, + null, + null, + ) + + return out.wrapMatrix() + } + + override fun Point.plus(other: Point): EjmlDoubleVector { + val out = DMatrixSparseCSC(1, 1) + + CommonOps_DSCC.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra.one, + other.toEjml().origin, + out, + null, + null, + ) + + return out.wrapVector() + } + + override fun Point.minus(other: Point): EjmlDoubleVector { + val out = DMatrixSparseCSC(1, 1) + + CommonOps_DSCC.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra { -one }, + other.toEjml().origin, + out, + null, + null, + ) + + return out.wrapVector() + } + + override fun Double.times(m: Matrix): EjmlDoubleMatrix = m * this + + override fun Point.times(value: Double): EjmlDoubleVector { + val res = DMatrixSparseCSC(1, 1) + CommonOps_DSCC.scale(value, toEjml().origin, res) + return res.wrapVector() + } + + override fun Double.times(v: Point): EjmlDoubleVector = v * this + + @UnstableKMathAPI + override fun computeFeature(structure: Matrix, type: KClass): F? { + structure.getFeature(type)?.let { return it } + val origin = structure.toEjml().origin + + return when (type) { + QRDecompositionFeature::class -> object : QRDecompositionFeature { + private val qr by lazy { + DecompositionFactory_DSCC.qr(FillReducing.NONE).apply { decompose(origin.copy()) } + } + + override val q: Matrix by lazy { + qr.getQ(null, false).wrapMatrix().withFeature(OrthogonalFeature) + } + + override val r: Matrix by lazy { qr.getR(null, false).wrapMatrix().withFeature(UFeature) } + } + + CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature { + override val l: Matrix by lazy { + val cholesky = + DecompositionFactory_DSCC.cholesky().apply { decompose(origin.copy()) } + + (cholesky.getT(null) as DMatrix).wrapMatrix().withFeature(LFeature) + } + } + + LUDecompositionFeature::class, DeterminantFeature::class, InverseMatrixFeature::class -> object : + LUDecompositionFeature, DeterminantFeature, InverseMatrixFeature { + private val lu by lazy { + DecompositionFactory_DSCC.lu(FillReducing.NONE).apply { decompose(origin.copy()) } + } + + override val l: Matrix by lazy { + lu.getLower(null).wrapMatrix().withFeature(LFeature) + } + + override val u: Matrix by lazy { + lu.getUpper(null).wrapMatrix().withFeature(UFeature) + } + + override val inverse: Matrix by lazy { + var a = origin + val inverse = DMatrixRMaj(1, 1) + val solver = LinearSolverFactory_DSCC.lu(FillReducing.NONE) + if (solver.modifiesA()) a = a.copy() + val i = CommonOps_DDRM.identity(a.numRows) + solver.solve(i, inverse) + inverse.wrapMatrix() + } + + override val determinant: Double by lazy { elementAlgebra.number(lu.computeDeterminant().real) } + } + + else -> null + }?.let{ + type.cast(it) + } + } + + /** + * Solves for *x* in the following equation: *x = [a] -1 · [b]*. + * + * @param a the base matrix. + * @param b n by p matrix. + * @return the solution for *x* that is n by p. + */ + public fun solve(a: Matrix, b: Matrix): EjmlDoubleMatrix { + val res = DMatrixSparseCSC(1, 1) + CommonOps_DSCC.solve(DMatrixSparseCSC(a.toEjml().origin), DMatrixSparseCSC(b.toEjml().origin), res) + return res.wrapMatrix() + } + + /** + * Solves for *x* in the following equation: *x = [a] -1 · [b]*. + * + * @param a the base matrix. + * @param b n by p vector. + * @return the solution for *x* that is n by p. + */ + public fun solve(a: Matrix, b: Point): EjmlDoubleVector { + val res = DMatrixSparseCSC(1, 1) + CommonOps_DSCC.solve(DMatrixSparseCSC(a.toEjml().origin), DMatrixSparseCSC(b.toEjml().origin), res) + return EjmlDoubleVector(res) + } +} + +/** + * [EjmlLinearSpace] implementation based on [CommonOps_FSCC], [DecompositionFactory_FSCC] operations and + * [FMatrixSparseCSC] matrices. + */ +public object EjmlLinearSpaceFSCC : EjmlLinearSpace() { + /** + * The [FloatField] reference. + */ + override val elementAlgebra: FloatField get() = FloatField + + @Suppress("UNCHECKED_CAST") + override fun Matrix.toEjml(): EjmlFloatMatrix = when { + this is EjmlFloatMatrix<*> && origin is FMatrixSparseCSC -> this as EjmlFloatMatrix + else -> buildMatrix(rowNum, colNum) { i, j -> get(i, j) } + } + + @Suppress("UNCHECKED_CAST") + override fun Point.toEjml(): EjmlFloatVector = when { + this is EjmlFloatVector<*> && origin is FMatrixSparseCSC -> this as EjmlFloatVector + else -> EjmlFloatVector(FMatrixSparseCSC(size, 1).also { + (0 until it.numRows).forEach { row -> it[row, 0] = get(row) } + }) + } + + override fun buildMatrix( + rows: Int, + columns: Int, + initializer: FloatField.(i: Int, j: Int) -> Float, + ): EjmlFloatMatrix = FMatrixSparseCSC(rows, columns).also { + (0 until rows).forEach { row -> + (0 until columns).forEach { col -> it[row, col] = elementAlgebra.initializer(row, col) } + } + }.wrapMatrix() + + override fun buildVector( + size: Int, + initializer: FloatField.(Int) -> Float, + ): EjmlFloatVector = EjmlFloatVector(FMatrixSparseCSC(size, 1).also { + (0 until it.numRows).forEach { row -> it[row, 0] = elementAlgebra.initializer(row) } + }) + + private fun T.wrapMatrix() = EjmlFloatMatrix(this) + private fun T.wrapVector() = EjmlFloatVector(this) + + override fun Matrix.unaryMinus(): Matrix = this * elementAlgebra { -one } + + override fun Matrix.dot(other: Matrix): EjmlFloatMatrix { + val out = FMatrixSparseCSC(1, 1) + CommonOps_FSCC.mult(toEjml().origin, other.toEjml().origin, out) + return out.wrapMatrix() + } + + override fun Matrix.dot(vector: Point): EjmlFloatVector { + val out = FMatrixSparseCSC(1, 1) + CommonOps_FSCC.mult(toEjml().origin, vector.toEjml().origin, out) + return out.wrapVector() + } + + override operator fun Matrix.minus(other: Matrix): EjmlFloatMatrix { + val out = FMatrixSparseCSC(1, 1) + + CommonOps_FSCC.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra { -one }, + other.toEjml().origin, + out, + null, + null, + ) + + return out.wrapMatrix() + } + + override operator fun Matrix.times(value: Float): EjmlFloatMatrix { + val res = FMatrixSparseCSC(1, 1) + CommonOps_FSCC.scale(value, toEjml().origin, res) + return res.wrapMatrix() + } + + override fun Point.unaryMinus(): EjmlFloatVector { + val res = FMatrixSparseCSC(1, 1) + CommonOps_FSCC.changeSign(toEjml().origin, res) + return res.wrapVector() + } + + override fun Matrix.plus(other: Matrix): EjmlFloatMatrix { + val out = FMatrixSparseCSC(1, 1) + + CommonOps_FSCC.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra.one, + other.toEjml().origin, + out, + null, + null, + ) + + return out.wrapMatrix() + } + + override fun Point.plus(other: Point): EjmlFloatVector { + val out = FMatrixSparseCSC(1, 1) + + CommonOps_FSCC.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra.one, + other.toEjml().origin, + out, + null, + null, + ) + + return out.wrapVector() + } + + override fun Point.minus(other: Point): EjmlFloatVector { + val out = FMatrixSparseCSC(1, 1) + + CommonOps_FSCC.add( + elementAlgebra.one, + toEjml().origin, + elementAlgebra { -one }, + other.toEjml().origin, + out, + null, + null, + ) + + return out.wrapVector() + } + + override fun Float.times(m: Matrix): EjmlFloatMatrix = m * this + + override fun Point.times(value: Float): EjmlFloatVector { + val res = FMatrixSparseCSC(1, 1) + CommonOps_FSCC.scale(value, toEjml().origin, res) + return res.wrapVector() + } + + override fun Float.times(v: Point): EjmlFloatVector = v * this + + @UnstableKMathAPI + override fun computeFeature(structure: Matrix, type: KClass): F? { + structure.getFeature(type)?.let { return it } + val origin = structure.toEjml().origin + + return when (type) { + QRDecompositionFeature::class -> object : QRDecompositionFeature { + private val qr by lazy { + DecompositionFactory_FSCC.qr(FillReducing.NONE).apply { decompose(origin.copy()) } + } + + override val q: Matrix by lazy { + qr.getQ(null, false).wrapMatrix().withFeature(OrthogonalFeature) + } + + override val r: Matrix by lazy { qr.getR(null, false).wrapMatrix().withFeature(UFeature) } + } + + CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature { + override val l: Matrix by lazy { + val cholesky = + DecompositionFactory_FSCC.cholesky().apply { decompose(origin.copy()) } + + (cholesky.getT(null) as FMatrix).wrapMatrix().withFeature(LFeature) + } + } + + LUDecompositionFeature::class, DeterminantFeature::class, InverseMatrixFeature::class -> object : + LUDecompositionFeature, DeterminantFeature, InverseMatrixFeature { + private val lu by lazy { + DecompositionFactory_FSCC.lu(FillReducing.NONE).apply { decompose(origin.copy()) } + } + + override val l: Matrix by lazy { + lu.getLower(null).wrapMatrix().withFeature(LFeature) + } + + override val u: Matrix by lazy { + lu.getUpper(null).wrapMatrix().withFeature(UFeature) + } + + override val inverse: Matrix by lazy { + var a = origin + val inverse = FMatrixRMaj(1, 1) + val solver = LinearSolverFactory_FSCC.lu(FillReducing.NONE) + if (solver.modifiesA()) a = a.copy() + val i = CommonOps_FDRM.identity(a.numRows) + solver.solve(i, inverse) + inverse.wrapMatrix() + } + + override val determinant: Float by lazy { elementAlgebra.number(lu.computeDeterminant().real) } + } + + else -> null + }?.let{ + type.cast(it) + } + } + + /** + * Solves for *x* in the following equation: *x = [a] -1 · [b]*. + * + * @param a the base matrix. + * @param b n by p matrix. + * @return the solution for *x* that is n by p. + */ + public fun solve(a: Matrix, b: Matrix): EjmlFloatMatrix { + val res = FMatrixSparseCSC(1, 1) + CommonOps_FSCC.solve(FMatrixSparseCSC(a.toEjml().origin), FMatrixSparseCSC(b.toEjml().origin), res) + return res.wrapMatrix() + } + + /** + * Solves for *x* in the following equation: *x = [a] -1 · [b]*. + * + * @param a the base matrix. + * @param b n by p vector. + * @return the solution for *x* that is n by p. + */ + public fun solve(a: Matrix, b: Point): EjmlFloatVector { + val res = FMatrixSparseCSC(1, 1) + CommonOps_FSCC.solve(FMatrixSparseCSC(a.toEjml().origin), FMatrixSparseCSC(b.toEjml().origin), res) + return EjmlFloatVector(res) + } +} + -- 2.34.1 From 32769d690683d8b1975f1d3380c2f6f3ffe49972 Mon Sep 17 00:00:00 2001 From: Erik Schouten Date: Fri, 15 Jul 2022 18:13:50 +0200 Subject: [PATCH 136/275] Dubins path --- kmath-trajectory/README.md | 32 ++++ kmath-trajectory/build.gradle.kts | 15 ++ .../kmath/trajectory/dubins/DubinsPath.kt | 30 +++ .../trajectory/dubins/DubinsPathFactory.kt | 171 ++++++++++++++++++ .../kscience/kmath/trajectory/segments/Arc.kt | 43 +++++ .../kmath/trajectory/segments/Line.kt | 23 +++ .../kmath/trajectory/segments/Segment.kt | 5 + .../trajectory/segments/components/Circle.kt | 11 ++ .../trajectory/segments/components/Pose2D.kt | 18 ++ .../space/kscience/kmath/trajectory/Math.kt | 27 +++ .../kmath/trajectory/dubins/DubinsTests.kt | 68 +++++++ .../kmath/trajectory/segments/ArcTests.kt | 24 +++ .../kmath/trajectory/segments/LineTests.kt | 33 ++++ settings.gradle.kts | 3 +- 14 files changed, 502 insertions(+), 1 deletion(-) create mode 100644 kmath-trajectory/README.md create mode 100644 kmath-trajectory/build.gradle.kts create mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPath.kt create mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPathFactory.kt create mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt create mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Line.kt create mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Segment.kt create mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/components/Circle.kt create mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/components/Pose2D.kt create mode 100644 kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/Math.kt create mode 100644 kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/dubins/DubinsTests.kt create mode 100644 kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/ArcTests.kt create mode 100644 kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/LineTests.kt diff --git a/kmath-trajectory/README.md b/kmath-trajectory/README.md new file mode 100644 index 000000000..cb2b6989f --- /dev/null +++ b/kmath-trajectory/README.md @@ -0,0 +1,32 @@ +# Module kmath-trajectory + + + +## Usage + +## Artifact: + +The Maven coordinates of this project are `space.kscience:kmath-trajectory:0.3.0`. + +**Gradle Groovy:** +```groovy +repositories { + maven { url 'https://repo.kotlin.link' } + mavenCentral() +} + +dependencies { + implementation 'space.kscience:kmath-trajectory:0.3.0' +} +``` +**Gradle Kotlin DSL:** +```kotlin +repositories { + maven("https://repo.kotlin.link") + mavenCentral() +} + +dependencies { + implementation("space.kscience:kmath-trajectory:0.3.0") +} +``` diff --git a/kmath-trajectory/build.gradle.kts b/kmath-trajectory/build.gradle.kts new file mode 100644 index 000000000..502867ee3 --- /dev/null +++ b/kmath-trajectory/build.gradle.kts @@ -0,0 +1,15 @@ +plugins { + kotlin("multiplatform") + id("ru.mipt.npm.gradle.common") + id("ru.mipt.npm.gradle.native") +} + +kotlin.sourceSets.commonMain { + dependencies { + api(projects.kmath.kmathGeometry) + } +} + +readme { + maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE +} diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPath.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPath.kt new file mode 100644 index 000000000..005d7fd60 --- /dev/null +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPath.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.trajectory.dubins + +import space.kscience.kmath.trajectory.segments.Arc +import space.kscience.kmath.trajectory.segments.Segment + +public class DubinsPath( + public val a: Arc, + public val b: Segment, + public val c: Arc, +) { + + public val type: TYPE = TYPE.valueOf( + arrayOf( + a.direction.name[0], + if (b is Arc) b.direction.name[0] else 'S', + c.direction.name[0] + ).toCharArray().concatToString() + ) + + public val length: Double = a.length + b.length + c.length + + public enum class TYPE { + RLR, LRL, RSR, LSL, RSL, LSR + } +} diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPathFactory.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPathFactory.kt new file mode 100644 index 000000000..98ed8ed32 --- /dev/null +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPathFactory.kt @@ -0,0 +1,171 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.trajectory.dubins + +import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo +import space.kscience.kmath.geometry.Line2D +import space.kscience.kmath.geometry.Vector2D +import space.kscience.kmath.trajectory.segments.Arc +import space.kscience.kmath.trajectory.segments.LineSegment +import space.kscience.kmath.trajectory.segments.components.Circle +import space.kscience.kmath.trajectory.segments.components.Pose2D +import space.kscience.kmath.trajectory.segments.length +import space.kscience.kmath.trajectory.segments.theta +import kotlin.math.acos +import kotlin.math.cos +import kotlin.math.sin + +public class DubinsPathFactory( + private val base: Pose2D, + private val direction: Pose2D, + private val turningRadius: Double +) { + + public val all: List get() = listOfNotNull(rlr, lrl, rsr, lsl, rsl, lsr) + public val shortest: DubinsPath get() = all.minByOrNull { it.length }!! + public operator fun get(type: DubinsPath.TYPE): DubinsPath? = all.find { it.type == type } + + public val rlr: DubinsPath? get () { + val c1 = base.getRightCircle(turningRadius) + val c2 = direction.getRightCircle(turningRadius) + val centers = Line2D(c1.center, c2.center) + return if (centers.length < turningRadius * 4) { + var theta = (centers.theta - acos(centers.length / (turningRadius * 4))).theta + var dX = turningRadius * sin(theta) + var dY = turningRadius * cos(theta) + val p = Vector2D(c1.center.x + dX * 2, c1.center.y + dY * 2) + val e = Circle(p, turningRadius) + val p1 = Vector2D(c1.center.x + dX, c1.center.y + dY) + theta = (centers.theta + acos(centers.length / (turningRadius * 4))).theta + dX = turningRadius * sin(theta) + dY = turningRadius * cos(theta) + val p2 = Vector2D(e.center.x + dX, e.center.y + dY) + val a1 = Arc(c1.center, turningRadius, base, p1, Arc.Direction.RIGHT) + val a2 = Arc(e.center, turningRadius, p1, p2, Arc.Direction.LEFT) + val a3 = Arc(c2.center, turningRadius, p2, direction, Arc.Direction.RIGHT) + DubinsPath(a1, a2, a3) + } else { + null + } + } + + private val lrl: DubinsPath? get () { + val c1 = base.getLeftCircle(turningRadius) + val c2 = direction.getLeftCircle(turningRadius) + val centers = Line2D(c1.center, c2.center) + return if (centers.length < turningRadius * 4) { + var theta = (centers.theta + acos(centers.length / (turningRadius * 4))).theta + var dX = turningRadius * sin(theta) + var dY = turningRadius * cos(theta) + val p = Vector2D(c1.center.x + dX * 2, c1.center.y + dY * 2) + val e = Circle(p, turningRadius) + val p1 = Vector2D(c1.center.x + dX, c1.center.y + dY) + theta = (centers.theta - acos(centers.length / (turningRadius * 4))).theta + dX = turningRadius * sin(theta) + dY = turningRadius * cos(theta) + val p2 = Vector2D(e.center.x + dX, e.center.y + dY) + val a1 = Arc(c1.center, turningRadius, base, p1, Arc.Direction.LEFT) + val a2 = Arc(e.center, turningRadius, p1, p2, Arc.Direction.RIGHT) + val a3 = Arc(c2.center, turningRadius, p2, direction, Arc.Direction.LEFT) + DubinsPath(a1, a2, a3) + } else { + null + } + } + + public val rsr: DubinsPath? get () { + val c1 = base.getRightCircle(turningRadius) + val c2 = direction.getRightCircle(turningRadius) + val l = leftOuterTangent(c1, c2) + val a1 = Arc(c1.center, turningRadius, base, l.base, Arc.Direction.RIGHT) + val a3 = Arc(c2.center, turningRadius, l.direction, direction, Arc.Direction.RIGHT) + return DubinsPath(a1, LineSegment(l), a3) + } + + public val lsl: DubinsPath + get () { + val c1 = base.getLeftCircle(turningRadius) + val c2 = direction.getLeftCircle(turningRadius) + val l = rightOuterTangent(c1, c2) + val a1 = Arc(c1.center, turningRadius, base, l.base, Arc.Direction.LEFT) + val a3 = Arc(c2.center, turningRadius, l.direction, direction, Arc.Direction.LEFT) + return DubinsPath(a1, LineSegment(l), a3) + } + + public val rsl: DubinsPath? get () { + val c1 = base.getRightCircle(turningRadius) + val c2 = direction.getLeftCircle(turningRadius) + val l = rightInnerTangent(c1, c2) + return if (c1.center.distanceTo(c2.center) > turningRadius * 2 && l != null) { + val a1 = Arc(c1.center, turningRadius, base, l.base, Arc.Direction.RIGHT) + val a3 = Arc(c2.center, turningRadius, l.direction, direction, Arc.Direction.LEFT) + DubinsPath(a1, LineSegment(l), a3) + } else { + null + } + } + + public val lsr: DubinsPath? get () { + val c1 = base.getLeftCircle(turningRadius) + val c2 = direction.getRightCircle(turningRadius) + val l = leftInnerTangent(c1, c2) + return if (c1.center.distanceTo(c2.center) > turningRadius * 2 && l != null) { + val a1 = Arc(c1.center, turningRadius, base, l.base, Arc.Direction.LEFT) + val a3 = Arc(c2.center, turningRadius, l.direction, direction, Arc.Direction.RIGHT) + DubinsPath(a1, LineSegment(l), a3) + } else { + null + } + } +} + +private enum class SIDE { + LEFT, RIGHT +} + +private fun Pose2D.getLeftCircle(radius: Double): Circle = getTangentCircles(radius).first +private fun Pose2D.getRightCircle(radius: Double): Circle = getTangentCircles(radius).second +private fun Pose2D.getTangentCircles(radius: Double): Pair { + val dX = radius * cos(theta) + val dY = radius * sin(theta) + return Circle(Vector2D(x - dX, y + dY), radius) to Circle(Vector2D(x + dX, y - dY), radius) +} + +private fun leftOuterTangent(a: Circle, b: Circle) = outerTangent(a, b, SIDE.LEFT) +private fun rightOuterTangent(a: Circle, b: Circle) = outerTangent(a, b, SIDE.RIGHT) +private fun outerTangent(a: Circle, b: Circle, side: SIDE): Line2D { + val centers = Line2D(a.center, b.center) + val p1 = when (side) { + SIDE.LEFT -> Vector2D( + a.center.x - a.radius * cos(centers.theta), + a.center.y + a.radius * sin(centers.theta) + ) + SIDE.RIGHT -> Vector2D( + a.center.x + a.radius * cos(centers.theta), + a.center.y - a.radius * sin(centers.theta) + ) + } + return Line2D(p1, Vector2D(p1.x + (centers.direction.x - centers.base.x), p1.y + (centers.direction.y - centers.base.y))) +} + +private fun leftInnerTangent(base: Circle, direction: Circle) = innerTangent(base, direction, SIDE.LEFT) +private fun rightInnerTangent(base: Circle, direction: Circle) = innerTangent(base, direction, SIDE.RIGHT) +private fun innerTangent(base: Circle, direction: Circle, side: SIDE): Line2D? { + val centers = Line2D(base.center, direction.center) + return if (centers.length > base.radius * 2) { + val angle = when (side) { + SIDE.LEFT -> centers.theta + acos(base.radius * 2 / centers.length) + SIDE.RIGHT -> centers.theta - acos(base.radius * 2 / centers.length) + }.theta + val dX = base.radius * sin(angle) + val dY = base.radius * cos(angle) + val p1 = Vector2D(base.center.x + dX, base.center.y + dY) + val p2 = Vector2D(direction.center.x - dX, direction.center.y - dY) + Line2D(p1, p2) + } else { + null + } +} diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt new file mode 100644 index 000000000..a7b2fe259 --- /dev/null +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt @@ -0,0 +1,43 @@ +package space.kscience.kmath.trajectory.segments + +import space.kscience.kmath.geometry.Line2D +import space.kscience.kmath.geometry.Vector2D +import space.kscience.kmath.trajectory.segments.components.Circle +import space.kscience.kmath.trajectory.segments.components.Pose2D +import kotlin.math.PI + +public class Arc( + center: Vector2D, + radius: Double, + a: Vector2D, + b: Vector2D, + internal val direction: Direction +) : Circle(center, radius), Segment { + + private val l1 = Line2D(center, a) + private val l2 = Line2D(center, b) + + internal val pose1 = calculatePose(a, l1.theta) + internal val pose2 = calculatePose(b, l2.theta) + private val angle = calculateAngle() + override val length: Double = calculateLength() + + public enum class Direction { + LEFT, RIGHT + } + + private fun calculateAngle() = + (if (direction == Direction.LEFT) l1.theta - l2.theta else l2.theta - l1.theta).theta + + private fun calculateLength(): Double { + val proportion = angle / (2 * PI) + return circumference * proportion + } + + private fun calculatePose(vector: Vector2D, theta: Double): Pose2D = + if (direction == Direction.LEFT) { + Pose2D(vector.x, vector.y, (theta - PI / 2).theta) + } else { + Pose2D(vector.x, vector.y, (theta + PI / 2).theta) + } +} diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Line.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Line.kt new file mode 100644 index 000000000..f63372016 --- /dev/null +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Line.kt @@ -0,0 +1,23 @@ +package space.kscience.kmath.trajectory.segments + +import space.kscience.kmath.geometry.Line2D +import space.kscience.kmath.operations.DoubleField.pow +import kotlin.math.PI +import kotlin.math.atan2 +import kotlin.math.sqrt + +public class LineSegment( + internal val line: Line2D +) : Segment { + override val length: Double + get() = line.length +} + +internal val Line2D.theta: Double + get() = atan2(direction.x - base.x, direction.y - base.y).theta + +internal val Line2D.length: Double + get() = sqrt((direction.x - base.x).pow(2) + (direction.y - base.y).pow(2)) + +internal val Double.theta: Double + get() = (this + (2 * PI)) % (2 * PI) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Segment.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Segment.kt new file mode 100644 index 000000000..8a1d086fc --- /dev/null +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Segment.kt @@ -0,0 +1,5 @@ +package space.kscience.kmath.trajectory.segments + +public interface Segment { + public val length: Double +} diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/components/Circle.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/components/Circle.kt new file mode 100644 index 000000000..946dd8c6e --- /dev/null +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/components/Circle.kt @@ -0,0 +1,11 @@ +package space.kscience.kmath.trajectory.segments.components + +import space.kscience.kmath.geometry.Vector2D +import kotlin.math.PI + +public open class Circle( + internal val center: Vector2D, + internal val radius: Double +) { + internal val circumference = radius * 2 * PI +} diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/components/Pose2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/components/Pose2D.kt new file mode 100644 index 000000000..6bcc3d308 --- /dev/null +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/components/Pose2D.kt @@ -0,0 +1,18 @@ +package space.kscience.kmath.trajectory.segments.components + +import space.kscience.kmath.geometry.Vector2D +import kotlin.math.cos +import kotlin.math.sin + +public class Pose2D( + override val x: Double, + override val y: Double, + public val theta: Double +) : Vector2D { + + internal constructor(vector: Vector2D, theta: Double) : this(vector.x, vector.y, theta) + + override fun toString(): String { + return "Pose2D(x=$x, y=$y, theta=$theta)" + } +} diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/Math.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/Math.kt new file mode 100644 index 000000000..9258e6b4a --- /dev/null +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/Math.kt @@ -0,0 +1,27 @@ +package space.kscience.kmath.trajectory + +import space.kscience.kmath.geometry.Line2D +import space.kscience.kmath.geometry.Vector2D +import space.kscience.kmath.trajectory.segments.components.Pose2D +import space.kscience.kmath.trajectory.segments.theta +import kotlin.math.PI +import kotlin.math.abs +import kotlin.math.sin + +private 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 Line2D.inverse() = Line2D(direction, base) +fun Line2D.shift(shift: Int, width: Double): Line2D { + val dX = width * sin(inverse().theta) + val dY = width * sin(theta) + + return Line2D( + Vector2D(base.x - dX * shift, base.y - dY * shift), + Vector2D(direction.x - dX * shift, direction.y - dY * shift) + ) +} diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/dubins/DubinsTests.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/dubins/DubinsTests.kt new file mode 100644 index 000000000..583e7a4e0 --- /dev/null +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/dubins/DubinsTests.kt @@ -0,0 +1,68 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.trajectory.dubins + +import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo +import space.kscience.kmath.geometry.Line2D +import space.kscience.kmath.geometry.Vector2D +import space.kscience.kmath.trajectory.segments.Arc +import space.kscience.kmath.trajectory.segments.LineSegment +import space.kscience.kmath.trajectory.equalFloat +import space.kscience.kmath.trajectory.equalsFloat +import space.kscience.kmath.trajectory.inverse +import space.kscience.kmath.trajectory.segments.components.Pose2D +import space.kscience.kmath.trajectory.segments.theta +import space.kscience.kmath.trajectory.shift +import kotlin.test.Test +import kotlin.test.assertNotNull +import kotlin.test.assertTrue + + +class DubinsTests { + + @Test + fun dubinsTest() { + val line = Line2D(Vector2D(0.0, 0.0), Vector2D(100.0, 100.0)) + val lineP1 = line.shift(1, 10.0).inverse() + + val start = Pose2D(line.direction, line.theta) + val end = Pose2D(lineP1.base, lineP1.theta) + val radius = 2.0 + val dubins = DubinsPathFactory(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[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.pose1)) + assertTrue(end.equalsFloat(path.c.pose2)) + + // Not working, theta double precision inaccuracy + if (path.b is Arc) { + val b = path.b as Arc + assertTrue(path.a.pose2.equalsFloat(b.pose1)) + assertTrue(path.c.pose1.equalsFloat(b.pose2)) + } else if (path.b is LineSegment) { + val b = (path.b as LineSegment).line + assertTrue(path.a.pose2.equalsFloat(Pose2D(b.base, b.theta))) + assertTrue(path.c.pose1.equalsFloat(Pose2D(b.direction, b.theta))) + } + } + } +} diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/ArcTests.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/ArcTests.kt new file mode 100644 index 000000000..73b3a1d87 --- /dev/null +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/ArcTests.kt @@ -0,0 +1,24 @@ +package space.kscience.kmath.trajectory.segments + +import space.kscience.kmath.geometry.Vector2D +import space.kscience.kmath.trajectory.radiansToDegrees +import space.kscience.kmath.trajectory.segments.components.Circle +import kotlin.test.Test +import kotlin.test.assertEquals + +class ArcTests { + + @Test + fun arcTest() { + val center = Vector2D(0.0, 0.0) + val radius = 2.0 + val expectedCircumference = 12.56637 + val circle = Circle(center, radius) + assertEquals(expectedCircumference, circle.circumference, 1.0) + + val arc = Arc(center, radius, Vector2D(-2.0, 0.0), Vector2D(0.0, 2.0), Arc.Direction.RIGHT) + assertEquals(expectedCircumference / 4, arc.length, 1.0) + assertEquals(0.0, arc.pose1.theta.radiansToDegrees()) + assertEquals(90.0, arc.pose2.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 new file mode 100644 index 000000000..30f5ef6d8 --- /dev/null +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/LineTests.kt @@ -0,0 +1,33 @@ +package space.kscience.kmath.trajectory.segments + +import space.kscience.kmath.geometry.Euclidean2DSpace +import space.kscience.kmath.geometry.Line2D +import space.kscience.kmath.geometry.Vector2D +import space.kscience.kmath.trajectory.radiansToDegrees +import kotlin.math.pow +import kotlin.math.sqrt +import kotlin.test.Test +import kotlin.test.assertEquals + +class LineTests { + + @Test + fun lineTest() { + val line = Line2D(Vector2D(0.0, 0.0), Vector2D(100.0, 100.0)) + assertEquals(sqrt(100.0.pow(2) + 100.0.pow(2)), line.length) + assertEquals(45.0, line.theta.radiansToDegrees()) + } + + @Test + fun lineAngleTest() { + val zero = Vector2D(0.0, 0.0) + val north = Line2D(Euclidean2DSpace.zero, Vector2D(0.0, 2.0)) + assertEquals(0.0, north.theta.radiansToDegrees()) + val east = Line2D(Euclidean2DSpace.zero, Vector2D(2.0, 0.0)) + assertEquals(90.0, east.theta.radiansToDegrees()) + val south = Line2D(Euclidean2DSpace.zero, Vector2D(0.0, -2.0)) + assertEquals(180.0, south.theta.radiansToDegrees()) + val west = Line2D(Euclidean2DSpace.zero, Vector2D(-2.0, 0.0)) + assertEquals(270.0, west.theta.radiansToDegrees()) + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index e3c621e9a..b564972c7 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -44,6 +44,7 @@ include( ":kmath-jupyter", ":kmath-symja", ":kmath-jafama", + ":kmath-trajectory", ":examples", ":benchmarks", -) \ No newline at end of file +) -- 2.34.1 From cdb116fa2009c36a2aaad9942032b35f83d4f8de Mon Sep 17 00:00:00 2001 From: Erik Schouten Date: Fri, 15 Jul 2022 18:55:37 +0200 Subject: [PATCH 137/275] Cleanup --- .../trajectory/dubins/DubinsPathFactory.kt | 94 +++++++++---------- 1 file changed, 43 insertions(+), 51 deletions(-) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPathFactory.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPathFactory.kt index 98ed8ed32..56875ac5b 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPathFactory.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPathFactory.kt @@ -32,51 +32,47 @@ public class DubinsPathFactory( val c1 = base.getRightCircle(turningRadius) val c2 = direction.getRightCircle(turningRadius) val centers = Line2D(c1.center, c2.center) - return if (centers.length < turningRadius * 4) { - var theta = (centers.theta - acos(centers.length / (turningRadius * 4))).theta - var dX = turningRadius * sin(theta) - var dY = turningRadius * cos(theta) - val p = Vector2D(c1.center.x + dX * 2, c1.center.y + dY * 2) - val e = Circle(p, turningRadius) - val p1 = Vector2D(c1.center.x + dX, c1.center.y + dY) - theta = (centers.theta + acos(centers.length / (turningRadius * 4))).theta - dX = turningRadius * sin(theta) - dY = turningRadius * cos(theta) - val p2 = Vector2D(e.center.x + dX, e.center.y + dY) - val a1 = Arc(c1.center, turningRadius, base, p1, Arc.Direction.RIGHT) - val a2 = Arc(e.center, turningRadius, p1, p2, Arc.Direction.LEFT) - val a3 = Arc(c2.center, turningRadius, p2, direction, Arc.Direction.RIGHT) - DubinsPath(a1, a2, a3) - } else { - null - } + if (centers.length > turningRadius * 4) return null + + var theta = (centers.theta - acos(centers.length / (turningRadius * 4))).theta + var dX = turningRadius * sin(theta) + var dY = turningRadius * cos(theta) + val p = Vector2D(c1.center.x + dX * 2, c1.center.y + dY * 2) + val e = Circle(p, turningRadius) + val p1 = Vector2D(c1.center.x + dX, c1.center.y + dY) + theta = (centers.theta + acos(centers.length / (turningRadius * 4))).theta + dX = turningRadius * sin(theta) + dY = turningRadius * cos(theta) + val p2 = Vector2D(e.center.x + dX, e.center.y + dY) + val a1 = Arc(c1.center, turningRadius, base, p1, Arc.Direction.RIGHT) + val a2 = Arc(e.center, turningRadius, p1, p2, Arc.Direction.LEFT) + val a3 = Arc(c2.center, turningRadius, p2, direction, Arc.Direction.RIGHT) + return DubinsPath(a1, a2, a3) } private val lrl: DubinsPath? get () { val c1 = base.getLeftCircle(turningRadius) val c2 = direction.getLeftCircle(turningRadius) val centers = Line2D(c1.center, c2.center) - return if (centers.length < turningRadius * 4) { - var theta = (centers.theta + acos(centers.length / (turningRadius * 4))).theta - var dX = turningRadius * sin(theta) - var dY = turningRadius * cos(theta) - val p = Vector2D(c1.center.x + dX * 2, c1.center.y + dY * 2) - val e = Circle(p, turningRadius) - val p1 = Vector2D(c1.center.x + dX, c1.center.y + dY) - theta = (centers.theta - acos(centers.length / (turningRadius * 4))).theta - dX = turningRadius * sin(theta) - dY = turningRadius * cos(theta) - val p2 = Vector2D(e.center.x + dX, e.center.y + dY) - val a1 = Arc(c1.center, turningRadius, base, p1, Arc.Direction.LEFT) - val a2 = Arc(e.center, turningRadius, p1, p2, Arc.Direction.RIGHT) - val a3 = Arc(c2.center, turningRadius, p2, direction, Arc.Direction.LEFT) - DubinsPath(a1, a2, a3) - } else { - null - } + if (centers.length > turningRadius * 4) return null + + var theta = (centers.theta + acos(centers.length / (turningRadius * 4))).theta + var dX = turningRadius * sin(theta) + var dY = turningRadius * cos(theta) + val p = Vector2D(c1.center.x + dX * 2, c1.center.y + dY * 2) + val e = Circle(p, turningRadius) + val p1 = Vector2D(c1.center.x + dX, c1.center.y + dY) + theta = (centers.theta - acos(centers.length / (turningRadius * 4))).theta + dX = turningRadius * sin(theta) + dY = turningRadius * cos(theta) + val p2 = Vector2D(e.center.x + dX, e.center.y + dY) + val a1 = Arc(c1.center, turningRadius, base, p1, Arc.Direction.LEFT) + val a2 = Arc(e.center, turningRadius, p1, p2, Arc.Direction.RIGHT) + val a3 = Arc(c2.center, turningRadius, p2, direction, Arc.Direction.LEFT) + return DubinsPath(a1, a2, a3) } - public val rsr: DubinsPath? get () { + public val rsr: DubinsPath get () { val c1 = base.getRightCircle(turningRadius) val c2 = direction.getRightCircle(turningRadius) val l = leftOuterTangent(c1, c2) @@ -99,26 +95,22 @@ public class DubinsPathFactory( val c1 = base.getRightCircle(turningRadius) val c2 = direction.getLeftCircle(turningRadius) val l = rightInnerTangent(c1, c2) - return if (c1.center.distanceTo(c2.center) > turningRadius * 2 && l != null) { - val a1 = Arc(c1.center, turningRadius, base, l.base, Arc.Direction.RIGHT) - val a3 = Arc(c2.center, turningRadius, l.direction, direction, Arc.Direction.LEFT) - DubinsPath(a1, LineSegment(l), a3) - } else { - null - } + if (c1.center.distanceTo(c2.center) < turningRadius * 2 || l == null) return null + + val a1 = Arc(c1.center, turningRadius, base, l.base, Arc.Direction.RIGHT) + val a3 = Arc(c2.center, turningRadius, l.direction, direction, Arc.Direction.LEFT) + return DubinsPath(a1, LineSegment(l), a3) } public val lsr: DubinsPath? get () { val c1 = base.getLeftCircle(turningRadius) val c2 = direction.getRightCircle(turningRadius) val l = leftInnerTangent(c1, c2) - return if (c1.center.distanceTo(c2.center) > turningRadius * 2 && l != null) { - val a1 = Arc(c1.center, turningRadius, base, l.base, Arc.Direction.LEFT) - val a3 = Arc(c2.center, turningRadius, l.direction, direction, Arc.Direction.RIGHT) - DubinsPath(a1, LineSegment(l), a3) - } else { - null - } + if (c1.center.distanceTo(c2.center) < turningRadius * 2 || l == null) return null + + val a1 = Arc(c1.center, turningRadius, base, l.base, Arc.Direction.LEFT) + val a3 = Arc(c2.center, turningRadius, l.direction, direction, Arc.Direction.RIGHT) + return DubinsPath(a1, LineSegment(l), a3) } } -- 2.34.1 From ada1141738328101da29f48af4ba71bc8fca2d30 Mon Sep 17 00:00:00 2001 From: Erik Schouten Date: Fri, 15 Jul 2022 18:57:10 +0200 Subject: [PATCH 138/275] Use Line distancTo function --- .../kotlin/space/kscience/kmath/trajectory/segments/Line.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Line.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Line.kt index f63372016..b3e93b5ed 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Line.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Line.kt @@ -1,5 +1,6 @@ package space.kscience.kmath.trajectory.segments +import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo import space.kscience.kmath.geometry.Line2D import space.kscience.kmath.operations.DoubleField.pow import kotlin.math.PI @@ -17,7 +18,7 @@ internal val Line2D.theta: Double get() = atan2(direction.x - base.x, direction.y - base.y).theta internal val Line2D.length: Double - get() = sqrt((direction.x - base.x).pow(2) + (direction.y - base.y).pow(2)) + get() = base.distanceTo(direction) internal val Double.theta: Double get() = (this + (2 * PI)) % (2 * PI) -- 2.34.1 From fa6d741869099923c120e709e11c521c85d425fc Mon Sep 17 00:00:00 2001 From: Erik Schouten Date: Fri, 15 Jul 2022 22:12:36 +0200 Subject: [PATCH 139/275] Small improvement in test classes, theta function --- .../trajectory/dubins/DubinsPathFactory.kt | 46 ++++++++++--------- .../kscience/kmath/trajectory/segments/Arc.kt | 11 ++--- .../kmath/trajectory/segments/Line.kt | 7 ++- .../trajectory/segments/components/Pose2D.kt | 7 +-- .../space/kscience/kmath/trajectory/Math.kt | 2 +- .../kmath/trajectory/segments/ArcTests.kt | 11 ++--- .../segments/components/CircleTests.kt | 23 ++++++++++ 7 files changed, 60 insertions(+), 47 deletions(-) create mode 100644 kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/components/CircleTests.kt diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPathFactory.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPathFactory.kt index 56875ac5b..818735a96 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPathFactory.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPathFactory.kt @@ -34,19 +34,19 @@ public class DubinsPathFactory( val centers = Line2D(c1.center, c2.center) if (centers.length > turningRadius * 4) return null - var theta = (centers.theta - acos(centers.length / (turningRadius * 4))).theta + var theta = theta(centers.theta - acos(centers.length / (turningRadius * 4))) var dX = turningRadius * sin(theta) var dY = turningRadius * cos(theta) val p = Vector2D(c1.center.x + dX * 2, c1.center.y + dY * 2) val e = Circle(p, turningRadius) val p1 = Vector2D(c1.center.x + dX, c1.center.y + dY) - theta = (centers.theta + acos(centers.length / (turningRadius * 4))).theta + theta = theta(centers.theta + acos(centers.length / (turningRadius * 4))) dX = turningRadius * sin(theta) dY = turningRadius * cos(theta) val p2 = Vector2D(e.center.x + dX, e.center.y + dY) - val a1 = Arc(c1.center, turningRadius, base, p1, Arc.Direction.RIGHT) - val a2 = Arc(e.center, turningRadius, p1, p2, Arc.Direction.LEFT) - val a3 = Arc(c2.center, turningRadius, p2, direction, Arc.Direction.RIGHT) + val a1 = Arc(c1.center, base, p1, Arc.Direction.RIGHT) + val a2 = Arc(e.center, p1, p2, Arc.Direction.LEFT) + val a3 = Arc(c2.center, p2, direction, Arc.Direction.RIGHT) return DubinsPath(a1, a2, a3) } @@ -56,19 +56,19 @@ public class DubinsPathFactory( val centers = Line2D(c1.center, c2.center) if (centers.length > turningRadius * 4) return null - var theta = (centers.theta + acos(centers.length / (turningRadius * 4))).theta + var theta = theta(centers.theta + acos(centers.length / (turningRadius * 4))) var dX = turningRadius * sin(theta) var dY = turningRadius * cos(theta) val p = Vector2D(c1.center.x + dX * 2, c1.center.y + dY * 2) val e = Circle(p, turningRadius) val p1 = Vector2D(c1.center.x + dX, c1.center.y + dY) - theta = (centers.theta - acos(centers.length / (turningRadius * 4))).theta + theta = theta(centers.theta - acos(centers.length / (turningRadius * 4))) dX = turningRadius * sin(theta) dY = turningRadius * cos(theta) val p2 = Vector2D(e.center.x + dX, e.center.y + dY) - val a1 = Arc(c1.center, turningRadius, base, p1, Arc.Direction.LEFT) - val a2 = Arc(e.center, turningRadius, p1, p2, Arc.Direction.RIGHT) - val a3 = Arc(c2.center, turningRadius, p2, direction, Arc.Direction.LEFT) + val a1 = Arc(c1.center, base, p1, Arc.Direction.LEFT) + val a2 = Arc(e.center, p1, p2, Arc.Direction.RIGHT) + val a3 = Arc(c2.center, p2, direction, Arc.Direction.LEFT) return DubinsPath(a1, a2, a3) } @@ -76,8 +76,8 @@ public class DubinsPathFactory( val c1 = base.getRightCircle(turningRadius) val c2 = direction.getRightCircle(turningRadius) val l = leftOuterTangent(c1, c2) - val a1 = Arc(c1.center, turningRadius, base, l.base, Arc.Direction.RIGHT) - val a3 = Arc(c2.center, turningRadius, l.direction, direction, Arc.Direction.RIGHT) + val a1 = Arc(c1.center, base, l.base, Arc.Direction.RIGHT) + val a3 = Arc(c2.center, l.direction, direction, Arc.Direction.RIGHT) return DubinsPath(a1, LineSegment(l), a3) } @@ -86,8 +86,8 @@ public class DubinsPathFactory( val c1 = base.getLeftCircle(turningRadius) val c2 = direction.getLeftCircle(turningRadius) val l = rightOuterTangent(c1, c2) - val a1 = Arc(c1.center, turningRadius, base, l.base, Arc.Direction.LEFT) - val a3 = Arc(c2.center, turningRadius, l.direction, direction, Arc.Direction.LEFT) + val a1 = Arc(c1.center, base, l.base, Arc.Direction.LEFT) + val a3 = Arc(c2.center, l.direction, direction, Arc.Direction.LEFT) return DubinsPath(a1, LineSegment(l), a3) } @@ -97,8 +97,8 @@ public class DubinsPathFactory( val l = rightInnerTangent(c1, c2) if (c1.center.distanceTo(c2.center) < turningRadius * 2 || l == null) return null - val a1 = Arc(c1.center, turningRadius, base, l.base, Arc.Direction.RIGHT) - val a3 = Arc(c2.center, turningRadius, l.direction, direction, Arc.Direction.LEFT) + val a1 = Arc(c1.center, base, l.base, Arc.Direction.RIGHT) + val a3 = Arc(c2.center, l.direction, direction, Arc.Direction.LEFT) return DubinsPath(a1, LineSegment(l), a3) } @@ -108,8 +108,8 @@ public class DubinsPathFactory( val l = leftInnerTangent(c1, c2) if (c1.center.distanceTo(c2.center) < turningRadius * 2 || l == null) return null - val a1 = Arc(c1.center, turningRadius, base, l.base, Arc.Direction.LEFT) - val a3 = Arc(c2.center, turningRadius, l.direction, direction, Arc.Direction.RIGHT) + val a1 = Arc(c1.center, base, l.base, Arc.Direction.LEFT) + val a3 = Arc(c2.center, l.direction, direction, Arc.Direction.RIGHT) return DubinsPath(a1, LineSegment(l), a3) } } @@ -148,10 +148,12 @@ private fun rightInnerTangent(base: Circle, direction: Circle) = innerTangent(ba private fun innerTangent(base: Circle, direction: Circle, side: SIDE): Line2D? { val centers = Line2D(base.center, direction.center) return if (centers.length > base.radius * 2) { - val angle = when (side) { - SIDE.LEFT -> centers.theta + acos(base.radius * 2 / centers.length) - SIDE.RIGHT -> centers.theta - acos(base.radius * 2 / centers.length) - }.theta + val angle = theta( + when (side) { + SIDE.LEFT -> centers.theta + acos(base.radius * 2 / centers.length) + SIDE.RIGHT -> centers.theta - acos(base.radius * 2 / centers.length) + } + ) val dX = base.radius * sin(angle) val dY = base.radius * cos(angle) val p1 = Vector2D(base.center.x + dX, base.center.y + dY) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt index a7b2fe259..b8a81a070 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt @@ -1,5 +1,6 @@ package space.kscience.kmath.trajectory.segments +import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo import space.kscience.kmath.geometry.Line2D import space.kscience.kmath.geometry.Vector2D import space.kscience.kmath.trajectory.segments.components.Circle @@ -8,11 +9,10 @@ import kotlin.math.PI public class Arc( center: Vector2D, - radius: Double, a: Vector2D, b: Vector2D, internal val direction: Direction -) : Circle(center, radius), Segment { +) : Circle(center, center.distanceTo(a)), Segment { private val l1 = Line2D(center, a) private val l2 = Line2D(center, b) @@ -26,8 +26,7 @@ public class Arc( LEFT, RIGHT } - private fun calculateAngle() = - (if (direction == Direction.LEFT) l1.theta - l2.theta else l2.theta - l1.theta).theta + private fun calculateAngle() = theta(if (direction == Direction.LEFT) l1.theta - l2.theta else l2.theta - l1.theta) private fun calculateLength(): Double { val proportion = angle / (2 * PI) @@ -36,8 +35,8 @@ public class Arc( private fun calculatePose(vector: Vector2D, theta: Double): Pose2D = if (direction == Direction.LEFT) { - Pose2D(vector.x, vector.y, (theta - PI / 2).theta) + Pose2D(vector.x, vector.y, theta(theta - PI / 2)) } else { - Pose2D(vector.x, vector.y, (theta + PI / 2).theta) + Pose2D(vector.x, vector.y, theta(theta + PI / 2)) } } diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Line.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Line.kt index b3e93b5ed..0e23b27f1 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Line.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Line.kt @@ -7,7 +7,7 @@ import kotlin.math.PI import kotlin.math.atan2 import kotlin.math.sqrt -public class LineSegment( +public data class LineSegment( internal val line: Line2D ) : Segment { override val length: Double @@ -15,10 +15,9 @@ public class LineSegment( } internal val Line2D.theta: Double - get() = atan2(direction.x - base.x, direction.y - base.y).theta + get() = theta(atan2(direction.x - base.x, direction.y - base.y)) internal val Line2D.length: Double get() = base.distanceTo(direction) -internal val Double.theta: Double - get() = (this + (2 * PI)) % (2 * PI) +internal fun theta(theta: Double) = (theta + (2 * PI)) % (2 * PI) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/components/Pose2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/components/Pose2D.kt index 6bcc3d308..d00dfbd96 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/components/Pose2D.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/components/Pose2D.kt @@ -4,15 +4,10 @@ import space.kscience.kmath.geometry.Vector2D import kotlin.math.cos import kotlin.math.sin -public class Pose2D( +public data class Pose2D( override val x: Double, override val y: Double, public val theta: Double ) : Vector2D { - internal constructor(vector: Vector2D, theta: Double) : this(vector.x, vector.y, theta) - - override fun toString(): String { - return "Pose2D(x=$x, y=$y, theta=$theta)" - } } 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 9258e6b4a..f52bb56f2 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 @@ -8,7 +8,7 @@ import kotlin.math.PI import kotlin.math.abs import kotlin.math.sin -private const val maxFloatDelta = 0.000001 +const val maxFloatDelta = 0.000001 fun Double.radiansToDegrees() = this * 180 / PI 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 73b3a1d87..a59643c0c 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,14 +10,9 @@ class ArcTests { @Test fun arcTest() { - val center = Vector2D(0.0, 0.0) - val radius = 2.0 - val expectedCircumference = 12.56637 - val circle = Circle(center, radius) - assertEquals(expectedCircumference, circle.circumference, 1.0) - - val arc = Arc(center, radius, Vector2D(-2.0, 0.0), Vector2D(0.0, 2.0), Arc.Direction.RIGHT) - assertEquals(expectedCircumference / 4, arc.length, 1.0) + val circle = Circle(Vector2D(0.0, 0.0), 2.0) + val arc = Arc(circle.center, Vector2D(-2.0, 0.0), Vector2D(0.0, 2.0), Arc.Direction.RIGHT) + assertEquals(circle.circumference / 4, arc.length, 1.0) assertEquals(0.0, arc.pose1.theta.radiansToDegrees()) assertEquals(90.0, arc.pose2.theta.radiansToDegrees()) } diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/components/CircleTests.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/components/CircleTests.kt new file mode 100644 index 000000000..6f28885e0 --- /dev/null +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/components/CircleTests.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.trajectory.segments.components + +import space.kscience.kmath.geometry.Vector2D +import space.kscience.kmath.trajectory.maxFloatDelta +import kotlin.test.Test +import kotlin.test.assertEquals + +class CircleTests { + + @Test + fun arcTest() { + val center = Vector2D(0.0, 0.0) + val radius = 2.0 + val expectedCircumference = 12.56637 + val circle = Circle(center, radius) + assertEquals(expectedCircumference, circle.circumference, maxFloatDelta) + } +} -- 2.34.1 From 4f88982734acfdfa5f771c3c9c3705801ab00781 Mon Sep 17 00:00:00 2001 From: Erik Schouten Date: Fri, 15 Jul 2022 22:13:50 +0200 Subject: [PATCH 140/275] Formatting --- .../trajectory/dubins/DubinsPathFactory.kt | 158 +++++++++--------- 1 file changed, 83 insertions(+), 75 deletions(-) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPathFactory.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPathFactory.kt index 818735a96..91287b952 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPathFactory.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPathFactory.kt @@ -28,90 +28,95 @@ public class DubinsPathFactory( public val shortest: DubinsPath get() = all.minByOrNull { it.length }!! public operator fun get(type: DubinsPath.TYPE): DubinsPath? = all.find { it.type == type } - public val rlr: DubinsPath? get () { - val c1 = base.getRightCircle(turningRadius) - val c2 = direction.getRightCircle(turningRadius) - val centers = Line2D(c1.center, c2.center) - if (centers.length > turningRadius * 4) return null + public val rlr: DubinsPath? + get() { + val c1 = base.getRightCircle(turningRadius) + val c2 = direction.getRightCircle(turningRadius) + val centers = Line2D(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 = Vector2D(c1.center.x + dX * 2, c1.center.y + dY * 2) - val e = Circle(p, turningRadius) - val p1 = Vector2D(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 = Vector2D(e.center.x + dX, e.center.y + dY) - val a1 = Arc(c1.center, base, p1, Arc.Direction.RIGHT) - val a2 = Arc(e.center, p1, p2, Arc.Direction.LEFT) - val a3 = Arc(c2.center, p2, direction, Arc.Direction.RIGHT) - return DubinsPath(a1, a2, a3) - } + var theta = theta(centers.theta - acos(centers.length / (turningRadius * 4))) + var dX = turningRadius * sin(theta) + var dY = turningRadius * cos(theta) + val p = Vector2D(c1.center.x + dX * 2, c1.center.y + dY * 2) + val e = Circle(p, turningRadius) + val p1 = Vector2D(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 = Vector2D(e.center.x + dX, e.center.y + dY) + val a1 = Arc(c1.center, base, p1, Arc.Direction.RIGHT) + val a2 = Arc(e.center, p1, p2, Arc.Direction.LEFT) + val a3 = Arc(c2.center, p2, direction, Arc.Direction.RIGHT) + return DubinsPath(a1, a2, a3) + } - private val lrl: DubinsPath? get () { - val c1 = base.getLeftCircle(turningRadius) - val c2 = direction.getLeftCircle(turningRadius) - val centers = Line2D(c1.center, c2.center) - if (centers.length > turningRadius * 4) return null + private val lrl: DubinsPath? + get() { + val c1 = base.getLeftCircle(turningRadius) + val c2 = direction.getLeftCircle(turningRadius) + val centers = Line2D(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 = Vector2D(c1.center.x + dX * 2, c1.center.y + dY * 2) - val e = Circle(p, turningRadius) - val p1 = Vector2D(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 = Vector2D(e.center.x + dX, e.center.y + dY) - val a1 = Arc(c1.center, base, p1, Arc.Direction.LEFT) - val a2 = Arc(e.center, p1, p2, Arc.Direction.RIGHT) - val a3 = Arc(c2.center, p2, direction, Arc.Direction.LEFT) - return DubinsPath(a1, a2, a3) - } + var theta = theta(centers.theta + acos(centers.length / (turningRadius * 4))) + var dX = turningRadius * sin(theta) + var dY = turningRadius * cos(theta) + val p = Vector2D(c1.center.x + dX * 2, c1.center.y + dY * 2) + val e = Circle(p, turningRadius) + val p1 = Vector2D(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 = Vector2D(e.center.x + dX, e.center.y + dY) + val a1 = Arc(c1.center, base, p1, Arc.Direction.LEFT) + val a2 = Arc(e.center, p1, p2, Arc.Direction.RIGHT) + val a3 = Arc(c2.center, p2, direction, Arc.Direction.LEFT) + return DubinsPath(a1, a2, a3) + } - public val rsr: DubinsPath get () { - val c1 = base.getRightCircle(turningRadius) - val c2 = direction.getRightCircle(turningRadius) - val l = leftOuterTangent(c1, c2) - val a1 = Arc(c1.center, base, l.base, Arc.Direction.RIGHT) - val a3 = Arc(c2.center, l.direction, direction, Arc.Direction.RIGHT) - return DubinsPath(a1, LineSegment(l), a3) - } + public val rsr: DubinsPath + get() { + val c1 = base.getRightCircle(turningRadius) + val c2 = direction.getRightCircle(turningRadius) + val l = leftOuterTangent(c1, c2) + val a1 = Arc(c1.center, base, l.base, Arc.Direction.RIGHT) + val a3 = Arc(c2.center, l.direction, direction, Arc.Direction.RIGHT) + return DubinsPath(a1, LineSegment(l), a3) + } public val lsl: DubinsPath - get () { - val c1 = base.getLeftCircle(turningRadius) - val c2 = direction.getLeftCircle(turningRadius) - val l = rightOuterTangent(c1, c2) - val a1 = Arc(c1.center, base, l.base, Arc.Direction.LEFT) - val a3 = Arc(c2.center, l.direction, direction, Arc.Direction.LEFT) - return DubinsPath(a1, LineSegment(l), a3) - } + get() { + val c1 = base.getLeftCircle(turningRadius) + val c2 = direction.getLeftCircle(turningRadius) + val l = rightOuterTangent(c1, c2) + val a1 = Arc(c1.center, base, l.base, Arc.Direction.LEFT) + val a3 = Arc(c2.center, l.direction, direction, Arc.Direction.LEFT) + return DubinsPath(a1, LineSegment(l), a3) + } - public val rsl: DubinsPath? get () { - val c1 = base.getRightCircle(turningRadius) - val c2 = direction.getLeftCircle(turningRadius) - val l = rightInnerTangent(c1, c2) - if (c1.center.distanceTo(c2.center) < turningRadius * 2 || l == null) return null + public val rsl: DubinsPath? + get() { + val c1 = base.getRightCircle(turningRadius) + val c2 = direction.getLeftCircle(turningRadius) + val l = rightInnerTangent(c1, c2) + if (c1.center.distanceTo(c2.center) < turningRadius * 2 || l == null) return null - val a1 = Arc(c1.center, base, l.base, Arc.Direction.RIGHT) - val a3 = Arc(c2.center, l.direction, direction, Arc.Direction.LEFT) - return DubinsPath(a1, LineSegment(l), a3) - } + val a1 = Arc(c1.center, base, l.base, Arc.Direction.RIGHT) + val a3 = Arc(c2.center, l.direction, direction, Arc.Direction.LEFT) + return DubinsPath(a1, LineSegment(l), a3) + } - public val lsr: DubinsPath? get () { - val c1 = base.getLeftCircle(turningRadius) - val c2 = direction.getRightCircle(turningRadius) - val l = leftInnerTangent(c1, c2) - if (c1.center.distanceTo(c2.center) < turningRadius * 2 || l == null) return null + public val lsr: DubinsPath? + get() { + val c1 = base.getLeftCircle(turningRadius) + val c2 = direction.getRightCircle(turningRadius) + val l = leftInnerTangent(c1, c2) + if (c1.center.distanceTo(c2.center) < turningRadius * 2 || l == null) return null - val a1 = Arc(c1.center, base, l.base, Arc.Direction.LEFT) - val a3 = Arc(c2.center, l.direction, direction, Arc.Direction.RIGHT) - return DubinsPath(a1, LineSegment(l), a3) - } + val a1 = Arc(c1.center, base, l.base, Arc.Direction.LEFT) + val a3 = Arc(c2.center, l.direction, direction, Arc.Direction.RIGHT) + return DubinsPath(a1, LineSegment(l), a3) + } } private enum class SIDE { @@ -140,7 +145,10 @@ private fun outerTangent(a: Circle, b: Circle, side: SIDE): Line2D { a.center.y - a.radius * sin(centers.theta) ) } - return Line2D(p1, Vector2D(p1.x + (centers.direction.x - centers.base.x), p1.y + (centers.direction.y - centers.base.y))) + return Line2D( + p1, + Vector2D(p1.x + (centers.direction.x - centers.base.x), p1.y + (centers.direction.y - centers.base.y)) + ) } private fun leftInnerTangent(base: Circle, direction: Circle) = innerTangent(base, direction, SIDE.LEFT) -- 2.34.1 From 68add4cb5f189d30a7ab5156d141beec97746b02 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 16 Jul 2022 11:35:50 +0300 Subject: [PATCH 141/275] Refactor test naming --- CHANGELOG.md | 1 + .../{DerivativeStructureExpressionTest.kt => DSTest.kt} | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) rename kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/{DerivativeStructureExpressionTest.kt => DSTest.kt} (98%) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4b8c06cf..ec993fb36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## [Unreleased] ### Added +- Autodiff for generic algebra elements in core! ### Changed - Kotlin 1.7 diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpressionTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DSTest.kt similarity index 98% rename from kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpressionTest.kt rename to kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DSTest.kt index e5bc9805a..727a918ec 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DerivativeStructureExpressionTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DSTest.kt @@ -25,7 +25,7 @@ internal inline fun diff( DSField(DoubleField, ::DoubleBuffer, order, mapOf(*parameters)).block() } -internal class AutoDiffTest { +internal class DSTest { private val x by symbol private val y by symbol -- 2.34.1 From 579511a5ee0b598fd0e72863ad69f33456e84996 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sat, 16 Jul 2022 16:07:03 +0300 Subject: [PATCH 142/275] Add utilities for maps. Fix some tests. --- .../LabeledPolynomial.kt | 171 ++---- .../ListPolynomial.kt | 24 +- .../NumberedPolynomial.kt | 80 +-- .../collectionUtils.kt | 500 ++++++++++++++++++ .../labeledConstructors.kt | 50 +- .../labeledUtil.kt | 24 +- .../numberedConstructors.kt | 47 +- .../numberedUtil.kt | 10 +- .../functions/NumberedConstructorsTest.kt | 12 +- 9 files changed, 606 insertions(+), 312 deletions(-) create mode 100644 kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/collectionUtils.kt 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 index 12bf9f839..b07674a1e 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/LabeledPolynomial.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/LabeledPolynomial.kt @@ -150,12 +150,7 @@ public class LabeledPolynomialSpace>( else with(coefficients) { if (isEmpty()) other.asPolynomial() else LabeledPolynomialAsIs( - toMutableMap() - .apply { - val degs = emptyMap() - - this[degs] = getOrElse(degs) { constantZero } + other - } + withPutOrChanged(emptyMap(), other.asConstant()) { it -> it + other } ) } /** @@ -168,12 +163,7 @@ public class LabeledPolynomialSpace>( else with(coefficients) { if (isEmpty()) (-other).asPolynomial() else LabeledPolynomialAsIs( - toMutableMap() - .apply { - val degs = emptyMap() - - this[degs] = getOrElse(degs) { constantZero } - other - } + withPutOrChanged(emptyMap(), (-other).asConstant()) { it -> it - other } ) } /** @@ -186,11 +176,7 @@ public class LabeledPolynomialSpace>( 0 -> zero 1 -> this else -> LabeledPolynomialAsIs( - coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this[degs]!! * other - } + coefficients.mapValues { (_, value) -> value * other } ) } @@ -204,12 +190,7 @@ public class LabeledPolynomialSpace>( else with(other.coefficients) { if (isEmpty()) this@plus.asPolynomial() else LabeledPolynomialAsIs( - toMutableMap() - .apply { - val degs = emptyMap() - - this[degs] = this@plus + getOrElse(degs) { constantZero } - } + withPutOrChanged(emptyMap(), this@plus.asConstant()) { it -> this@plus + it } ) } /** @@ -218,18 +199,14 @@ public class LabeledPolynomialSpace>( * The operation is equivalent to subtraction [this] copies of unit polynomial from [other]. */ public override operator fun Int.minus(other: LabeledPolynomial): LabeledPolynomial = - if (this == 0) -other - else with(other.coefficients) { - if (isEmpty()) this@minus.asPolynomial() - else LabeledPolynomialAsIs( - toMutableMap() - .apply { - forEach { (key, value) -> if (key.isNotEmpty()) this[key] = -value } - - val degs = emptyMap() - - this[degs] = this@minus - getOrElse(degs) { constantZero } - } + 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 }) + } ) } /** @@ -242,11 +219,7 @@ public class LabeledPolynomialSpace>( 0 -> zero 1 -> other else -> LabeledPolynomialAsIs( - other.coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this@times * this[degs]!! - } + other.coefficients.mapValues { (_, value) -> this@times * value } ) } @@ -305,41 +278,26 @@ public class LabeledPolynomialSpace>( with(other.coefficients) { if (isEmpty()) this@plus.asLabeledPolynomial() else LabeledPolynomialAsIs( - toMutableMap() - .apply { - val degs = emptyMap() - - this[degs] = this@plus + getOrElse(degs) { constantZero } - } + 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 = - with(other.coefficients) { - if (isEmpty()) this@minus.asLabeledPolynomial() - else LabeledPolynomialAsIs( - toMutableMap() - .apply { - forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } - - val degs = emptyMap() - - this[degs] = this@minus - getOrElse(degs) { constantZero } - } - ) - } + 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 - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this@times * this[degs]!! - } + other.coefficients.mapValues { this@times * it.value } ) /** @@ -349,12 +307,7 @@ public class LabeledPolynomialSpace>( with(coefficients) { if (isEmpty()) other.asLabeledPolynomial() else LabeledPolynomialAsIs( - toMutableMap() - .apply { - val degs = emptyMap() - - this[degs] = getOrElse(degs) { constantZero } + other - } + withPutOrChanged(emptyMap(), other) { it -> it + other } ) } /** @@ -364,12 +317,7 @@ public class LabeledPolynomialSpace>( with(coefficients) { if (isEmpty()) other.asLabeledPolynomial() else LabeledPolynomialAsIs( - toMutableMap() - .apply { - val degs = emptyMap() - - this[degs] = getOrElse(degs) { constantZero } - other - } + withPutOrChanged(emptyMap(), -other) { it -> it - other } ) } /** @@ -377,11 +325,7 @@ public class LabeledPolynomialSpace>( */ override operator fun LabeledPolynomial.times(other: C): LabeledPolynomial = LabeledPolynomialAsIs( - coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this[degs]!! * other - } + coefficients.mapValues { it.value * other } ) /** @@ -441,38 +385,27 @@ public class LabeledPolynomialSpace>( with(other.coefficients) { if (isEmpty()) this@plus.asPolynomial() else LabeledPolynomialAsIs( - toMutableMap() - .apply { - val degs = mapOf(this@plus to 1U) - - this[degs] = constantOne + getOrElse(degs) { constantZero } - } + 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 = - with(other.coefficients) { - if (isEmpty()) this@minus.asPolynomial() - else LabeledPolynomialAsIs( - toMutableMap() - .apply { - val theVariableDegs = mapOf(this@minus to 1U) - - forEach { (degs, c) -> if(degs != theVariableDegs) this[degs] = -c } - - this[theVariableDegs] = constantOne - getOrElse(theVariableDegs) { constantZero } - } - ) - } + 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.toMutableMap().also{ it[this] = if (this in it) it[this]!! + 1U else 1U } } + .mapKeys { (degs, _) -> degs.withPutOrChanged(this, 1u) { it -> it + 1u } } ) /** @@ -482,12 +415,7 @@ public class LabeledPolynomialSpace>( with(coefficients) { if (isEmpty()) other.asPolynomial() else LabeledPolynomialAsIs( - toMutableMap() - .apply { - val degs = mapOf(other to 1U) - - this[degs] = constantOne + getOrElse(degs) { constantZero } - } + withPutOrChanged(mapOf(other to 1U), constantOne) { it -> it + constantOne } ) } /** @@ -497,12 +425,7 @@ public class LabeledPolynomialSpace>( with(coefficients) { if (isEmpty()) other.asPolynomial() else LabeledPolynomialAsIs( - toMutableMap() - .apply { - val degs = mapOf(other to 1U) - - this[degs] = getOrElse(degs) { constantZero } - constantOne - } + withPutOrChanged(mapOf(other to 1U), -constantOne) { it -> it - constantOne } ) } /** @@ -511,7 +434,7 @@ public class LabeledPolynomialSpace>( public override operator fun LabeledPolynomial.times(other: Symbol): LabeledPolynomial = LabeledPolynomialAsIs( coefficients - .mapKeys { (degs, _) -> degs.toMutableMap().also{ it[other] = if (other in it) it[other]!! + 1U else 1U } } + .mapKeys { (degs, _) -> degs.withPutOrChanged(other, 1u) { it -> it + 1u } } ) /** @@ -526,10 +449,7 @@ public class LabeledPolynomialSpace>( */ override operator fun LabeledPolynomial.plus(other: LabeledPolynomial): LabeledPolynomial = LabeledPolynomialAsIs( - buildMap(coefficients.size + other.coefficients.size) { - coefficients.mapValuesTo(this) { it.value } - other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value } - } + mergeBy(coefficients, other.coefficients) { c1, c2 -> c1 + c2 } ) /** * Returns difference of the polynomials. @@ -537,8 +457,8 @@ public class LabeledPolynomialSpace>( override operator fun LabeledPolynomial.minus(other: LabeledPolynomial): LabeledPolynomial = LabeledPolynomialAsIs( buildMap(coefficients.size + other.coefficients.size) { - coefficients.mapValuesTo(this) { it.value } - other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value } + coefficients.copyTo(this) + other.coefficients.copyMapToBy(this, { _, c -> -c }, { currentC, newC -> currentC - newC }) } ) /** @@ -548,10 +468,9 @@ public class LabeledPolynomialSpace>( LabeledPolynomialAsIs( buildMap(coefficients.size * other.coefficients.size) { for ((degs1, c1) in coefficients) for ((degs2, c2) in other.coefficients) { - val degs = degs1.toMutableMap() - degs2.mapValuesTo(degs) { (variable, deg) -> degs.getOrElse(variable) { 0u } + deg } + val degs = mergeBy(degs1, degs2) { deg1, deg2 -> deg1 + deg2 } val c = c1 * c2 - this[degs] = if (degs in this) this[degs]!! + c else c + this.putOrChange(degs, c) { it -> it + c } } } ) @@ -581,10 +500,8 @@ public class LabeledPolynomialSpace>( public override val LabeledPolynomial.degrees: Map get() = buildMap { - coefficients.entries.forEach { (degs, _) -> - degs.mapValuesTo(this) { (variable, deg) -> - max(getOrElse(variable) { 0u }, deg) - } + coefficients.keys.forEach { degs -> + degs.copyToBy(this, ::max) } } /** 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 index 91b9c7658..17c42ac8c 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/ListPolynomial.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/ListPolynomial.kt @@ -109,11 +109,7 @@ public open class ListPolynomialSpace>( 0 -> zero 1 -> this else -> ListPolynomial( - coefficients - .toMutableList() - .apply { - for (deg in indices) this[deg] = this[deg] * other - } + coefficients.map { it * other } ) } @@ -167,11 +163,7 @@ public open class ListPolynomialSpace>( 0 -> zero 1 -> other else -> ListPolynomial( - other.coefficients - .toMutableList() - .apply { - for (deg in indices) this[deg] = this@times * this[deg] - } + other.coefficients.map { this@times * it } ) } @@ -214,11 +206,7 @@ public open class ListPolynomialSpace>( */ public override operator fun C.times(other: ListPolynomial): ListPolynomial = ListPolynomial( - other.coefficients - .toMutableList() - .apply { - for (deg in indices) this[deg] = this@times * this[deg] - } + other.coefficients.map { this@times * it } ) /** @@ -258,11 +246,7 @@ public open class ListPolynomialSpace>( */ public override operator fun ListPolynomial.times(other: C): ListPolynomial = ListPolynomial( - coefficients - .toMutableList() - .apply { - for (deg in indices) this[deg] = this[deg] * other - } + coefficients.map { it * other } ) /** 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 index 96c96e555..14c03ff7c 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/NumberedPolynomial.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/NumberedPolynomial.kt @@ -71,13 +71,7 @@ public class NumberedPolynomialSpace>( if (other == 0) this else NumberedPolynomialAsIs( - coefficients - .toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = getOrElse(degs) { constantZero } + other - } + coefficients.withPutOrChanged(emptyList(), other.asConstant()) { it -> it + other } ) /** * Returns difference between the polynomial and the integer represented as a polynomial. @@ -88,13 +82,7 @@ public class NumberedPolynomialSpace>( if (other == 0) this else NumberedPolynomialAsIs( - coefficients - .toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = getOrElse(degs) { constantZero } - other - } + coefficients.withPutOrChanged(emptyList(), (-other).asConstant()) { it -> it - other } ) /** * Returns product of the polynomial and the integer represented as a polynomial. @@ -106,11 +94,7 @@ public class NumberedPolynomialSpace>( 0 -> zero 1 -> this else -> NumberedPolynomialAsIs( - coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this[degs]!! * other - } + coefficients.mapValues { it.value * other } ) } @@ -123,13 +107,7 @@ public class NumberedPolynomialSpace>( if (this == 0) other else NumberedPolynomialAsIs( - other.coefficients - .toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = this@plus + getOrElse(degs) { constantZero } - } + other.coefficients.withPutOrChanged(emptyList(), this@plus.asConstant()) { it -> this@plus + it } ) /** * Returns difference between the integer represented as a polynomial and the polynomial. @@ -162,11 +140,7 @@ public class NumberedPolynomialSpace>( 0 -> zero 1 -> other else -> NumberedPolynomialAsIs( - other.coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this@times * this[degs]!! - } + other.coefficients.mapValues { this@times * it.value } ) } @@ -177,12 +151,7 @@ public class NumberedPolynomialSpace>( with(other.coefficients) { if (isEmpty()) NumberedPolynomialAsIs(mapOf(emptyList() to this@plus)) else NumberedPolynomialAsIs( - toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = this@plus + getOrElse(degs) { constantZero } - } + withPutOrChanged(emptyList(), this@plus) { it -> this@plus + it } ) } /** @@ -207,11 +176,7 @@ public class NumberedPolynomialSpace>( */ override operator fun C.times(other: NumberedPolynomial): NumberedPolynomial = NumberedPolynomialAsIs( - other.coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this@times * this[degs]!! - } + other.coefficients.mapValues { this@times * it.value } ) /** @@ -221,12 +186,7 @@ public class NumberedPolynomialSpace>( with(coefficients) { if (isEmpty()) NumberedPolynomialAsIs(mapOf(emptyList() to other)) else NumberedPolynomialAsIs( - toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = getOrElse(degs) { constantZero } + other - } + withPutOrChanged(emptyList(), other) { it -> it + other } ) } /** @@ -236,12 +196,7 @@ public class NumberedPolynomialSpace>( with(coefficients) { if (isEmpty()) NumberedPolynomialAsIs(mapOf(emptyList() to other)) else NumberedPolynomialAsIs( - toMutableMap() - .apply { - val degs = emptyList() - - this[degs] = getOrElse(degs) { constantZero } - other - } + withPutOrChanged(emptyList(), -other) { it -> it - other } ) } /** @@ -249,11 +204,7 @@ public class NumberedPolynomialSpace>( */ override operator fun NumberedPolynomial.times(other: C): NumberedPolynomial = NumberedPolynomialAsIs( - coefficients - .toMutableMap() - .apply { - for (degs in keys) this[degs] = this[degs]!! * other - } + coefficients.mapValues { it.value * other } ) /** @@ -274,10 +225,7 @@ public class NumberedPolynomialSpace>( */ override operator fun NumberedPolynomial.plus(other: NumberedPolynomial): NumberedPolynomial = NumberedPolynomialAsIs( - buildMap(coefficients.size + other.coefficients.size) { - coefficients.mapValuesTo(this) { it.value } - other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value } - } + mergeBy(coefficients, other.coefficients) { c1, c2 -> c1 + c2 } ) /** * Returns difference of the polynomials. @@ -285,8 +233,8 @@ public class NumberedPolynomialSpace>( override operator fun NumberedPolynomial.minus(other: NumberedPolynomial): NumberedPolynomial = NumberedPolynomialAsIs( buildMap(coefficients.size + other.coefficients.size) { - coefficients.mapValuesTo(this) { it.value } - other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value } + coefficients.copyTo(this) + other.coefficients.copyMapToBy(this, { _, c -> -c }, { currentC, newC -> currentC - newC }) } ) /** @@ -300,7 +248,7 @@ public class NumberedPolynomialSpace>( (0..max(degs1.lastIndex, degs2.lastIndex)) .map { degs1.getOrElse(it) { 0U } + degs2.getOrElse(it) { 0U } } val c = c1 * c2 - this[degs] = if (degs in this) this[degs]!! + c else c + putOrChange(degs, c) { it -> it + c } } } ) diff --git a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/collectionUtils.kt b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/collectionUtils.kt new file mode 100644 index 000000000..1d3da4c8b --- /dev/null +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/collectionUtils.kt @@ -0,0 +1,500 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.functions + +import kotlin.contracts.InvocationKind.* +import kotlin.contracts.contract + + +/** + * 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 transform(get(key)).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) + } + @Suppress("UNCHECKED_CAST") + return (if (key !in this) valueOnPut() else transformOnChange(get(key) as V)).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) }) + +// TODO: Docs +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 +} + +// TODO: Docs +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 +} + +// TODO: Docs +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) } + +// TODO: Docs +internal fun merge(map1: Map, map2: Map): Map { + val result = LinkedHashMap(map1.size + map2.size) + return mergeTo(map1, map2, result) +} + +// TODO: Docs +internal inline fun mergeBy(map1: Map, map2: Map, transform: (key: K, value1: V1, value2: V2) -> W): Map { + val result = LinkedHashMap(map1.size + map2.size) + return mergeToBy(map1, map2, result, transform) +} + +// TODO: Docs +internal inline fun mergeBy(map1: Map, map2: Map, transform: (value1: V1, value2: V2) -> W): Map = + mergeBy(map1, map2) { _, value1, value2 -> transform(value1, value2) } + +// TODO: Docs +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 +} + +// TODO: Docs +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 +} + +// TODO: Docs +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 +} + +// TODO: Docs +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) } + +// TODO: Docs +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) } + +// TODO: Docs +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) } + +// TODO: Docs +internal inline fun Iterable.associate(transform: (T) -> Pair, resolve: (key: K, currentValue: V, newValue: V) -> V): Map = + associateTo(LinkedHashMap(), transform, resolve) + +// TODO: Docs +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) + +// TODO: Docs +internal inline fun Iterable.associateBy(keySelector: (T) -> K, resolve: (key: K, currentValue: T, newValue: T) -> T): Map = + associateByTo(LinkedHashMap(), keySelector, resolve) + +// TODO: Docs +internal inline fun Iterable.associate(transform: (T) -> Pair, resolve: (currentValue: V, newValue: V) -> V): Map = + associateTo(LinkedHashMap(), transform, resolve) + +// TODO: Docs +internal inline fun Iterable.associateBy(keySelector: (T) -> K, valueTransform: (T) -> V, resolve: (currentValue: V, newValue: V) -> V): Map = + associateByTo(LinkedHashMap(), keySelector, valueTransform, resolve) + +// TODO: Docs +internal inline fun Iterable.associateBy(keySelector: (T) -> K, resolve: (currentValue: T, newValue: T) -> T): Map = + associateByTo(LinkedHashMap(), keySelector, resolve) + +// TODO: Docs +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) + +// TODO: Docs +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) + +// TODO: Docs +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) + +// TODO: Docs +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) + +// TODO: Docs +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) + +// TODO: Docs +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) + +// TODO: Docs +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) + +// TODO: Docs +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) + +// TODO: Docs +internal inline fun Map.mapKeys(transform: (Map.Entry) -> L, resolve: (key: L, currentValue: V, newValue: V) -> V): Map = + mapKeysTo(LinkedHashMap(size), transform, resolve) + +// TODO: Docs +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) + +// TODO: Docs +internal inline fun Map.mapKeys(transform: (Map.Entry) -> L, resolve: (currentValue: V, newValue: V) -> V): Map = + mapKeysTo(LinkedHashMap(size), transform, resolve) + +// TODO: Docs +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 index aa44660c1..43048089e 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/labeledConstructors.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/labeledConstructors.kt @@ -10,6 +10,7 @@ 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 /** @@ -76,17 +77,10 @@ public inline fun LabeledPolynomialWithoutCheck(vararg pairs: Pair LabeledPolynomial(coefs: Map, C>, add: (C, C) -> C) : LabeledPolynomial { - val fixedCoefs = mutableMapOf, C>() - - for (entry in coefs) { - val key = entry.key.cleanUp() - val value = entry.value - fixedCoefs[key] = if (key in fixedCoefs) add(fixedCoefs[key]!!, value) else value - } - - return LabeledPolynomial(fixedCoefs) -} +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". @@ -98,17 +92,10 @@ public fun LabeledPolynomial(coefs: Map, C>, add: (C, C) - * * @see LabeledPolynomialWithoutCheck */ -public fun LabeledPolynomial(pairs: Collection, C>>, add: (C, C) -> C) : LabeledPolynomial { - val fixedCoefs = mutableMapOf, C>() - - for (entry in pairs) { - val key = entry.first.cleanUp() - val value = entry.second - fixedCoefs[key] = if (key in fixedCoefs) add(fixedCoefs[key]!!, value) else value - } - - return LabeledPolynomial(fixedCoefs) -} +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". @@ -120,17 +107,10 @@ public fun LabeledPolynomial(pairs: Collection, C>>, * * @see LabeledPolynomialWithoutCheck */ -public fun LabeledPolynomial(vararg pairs: Pair, C>, add: (C, C) -> C) : LabeledPolynomial { - val fixedCoefs = mutableMapOf, C>() - - for (entry in pairs) { - val key = entry.first.cleanUp() - val value = entry.second - fixedCoefs[key] = if (key in fixedCoefs) add(fixedCoefs[key]!!, value) else value - } - - return LabeledPolynomial(fixedCoefs) -} +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 @@ -304,7 +284,7 @@ public class DSL1LabeledPolynomialTermSignatureBuilder { */ public infix fun Symbol.inPowerOf(deg: UInt) { if (deg == 0u) return - signature[this] = signature.getOrElse(this) { 0u } + deg + signature.putOrChange(this, deg) { it -> it + deg } } /** * Declares power of [this] variable of degree [deg]. @@ -362,7 +342,7 @@ public class DSL1LabeledPolynomialBuilder( * 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[signature] = if (signature in coefficients) add(coefficients[signature]!!, this@with) else this@with + coefficients.putOrChange(signature, this@with, add) } /** * Declares monomial with [this] coefficient and signature constructed by [block]. 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 index e3b35facc..a37a1fe39 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/labeledUtil.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/labeledUtil.kt @@ -7,10 +7,7 @@ package space.kscience.kmath.functions import space.kscience.kmath.expressions.Symbol 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.operations.* import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.jvm.JvmName @@ -56,7 +53,7 @@ public fun LabeledPolynomial.substitute(args: Map): Labe val deg = degs.getOrElse(variable) { 0u } if (deg == 0u) product else product * power(substitution, deg) } - this[newDegs] = if (newDegs in this) this[newDegs]!! + newC else newC + putOrChange(newDegs, newC, ::add) } } ) @@ -75,7 +72,7 @@ public fun LabeledPolynomial.substitute(ring: Ring, args: Map> LabeledPolynomial.antiderivativeWithRespectTo( buildMap(coefficients.size) { coefficients .forEach { (degs, c) -> - val newDegs = buildMap(degs.size + 1) { - put(variable, 1u) - for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) - } + val newDegs = degs.withPutOrChanged(variable, 1u) { it -> it + 1u } put( newDegs, c / multiplyByDoubling(one, newDegs[variable]!!) @@ -284,10 +278,7 @@ public fun > LabeledPolynomial.nthAntiderivativeWithRespectTo buildMap(coefficients.size) { coefficients .forEach { (degs, c) -> - val newDegs = buildMap(degs.size + 1) { - put(variable, order) - for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) - } + val newDegs = degs.withPutOrChanged(variable, order) { it -> it + order } put( newDegs, newDegs[variable]!!.let { deg -> @@ -314,10 +305,7 @@ public fun > LabeledPolynomial.nthAntiderivativeWithRespectTo buildMap(coefficients.size) { coefficients .forEach { (degs, c) -> - val newDegs = buildMap(degs.size + 1) { - for ((variable, order) in filteredVariablesAndOrders) put(variable, order) - for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) - } + val newDegs = mergeBy(degs, filteredVariablesAndOrders) { deg, order -> deg + order } put( newDegs, filteredVariablesAndOrders.entries.fold(c) { acc1, (index, order) -> 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 index ce0db3d17..ce49088ae 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/numberedConstructors.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/numberedConstructors.kt @@ -75,17 +75,10 @@ public inline fun NumberedPolynomialWithoutCheck(vararg pairs: Pair NumberedPolynomial(coefs: Map, C>, add: (C, C) -> C) : NumberedPolynomial { - val fixedCoefs = mutableMapOf, C>() - - for (entry in coefs) { - val key = entry.key.cleanUp() - val value = entry.value - fixedCoefs[key] = if (key in fixedCoefs) add(fixedCoefs[key]!!, value) else value - } - - return NumberedPolynomial(fixedCoefs) -} +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". @@ -97,17 +90,10 @@ public fun NumberedPolynomial(coefs: Map, C>, add: (C, C) -> C) : * * @see NumberedPolynomialWithoutCheck */ -public fun NumberedPolynomial(pairs: Collection, C>>, add: (C, C) -> C) : NumberedPolynomial { - val fixedCoefs = mutableMapOf, C>() - - for (entry in pairs) { - val key = entry.first.cleanUp() - val value = entry.second - fixedCoefs[key] = if (key in fixedCoefs) add(fixedCoefs[key]!!, value) else value - } - - return NumberedPolynomial(fixedCoefs) -} +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". @@ -119,17 +105,10 @@ public fun NumberedPolynomial(pairs: Collection, C>>, add: ( * * @see NumberedPolynomialWithoutCheck */ -public fun NumberedPolynomial(vararg pairs: Pair, C>, add: (C, C) -> C) : NumberedPolynomial { - val fixedCoefs = mutableMapOf, C>() - - for (entry in pairs) { - val key = entry.first.cleanUp() - val value = entry.second - fixedCoefs[key] = if (key in fixedCoefs) add(fixedCoefs[key]!!, value) else value - } - - return NumberedPolynomial(fixedCoefs) -} +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 @@ -349,7 +328,7 @@ public class DSL1NumberedPolynomialBuilder( * 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[signature] = if (signature in coefficients) add(coefficients[signature]!!, this@with) else this@with + coefficients.putOrChange(signature, this@with, add) } /** * Declares monomial with [this] coefficient and signature constructed by [block]. 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 index 9d88cd648..9f29cf31a 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/numberedUtil.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/numberedUtil.kt @@ -58,7 +58,7 @@ public fun NumberedPolynomial.substitute(args: Map): Number val deg = degs.getOrElse(variable) { 0u } if (deg == 0u) product else product * substitution.pow(deg.toInt()) } - this[newDegs] = if (newDegs !in this) newC else this[newDegs]!! + newC + putOrChange(newDegs, newC) { it -> it + newC } } } ) @@ -76,7 +76,7 @@ public fun NumberedPolynomial.substitute(ring: Ring, args: Map val deg = degs.getOrElse(variable) { 0u } if (deg == 0u) product else product * power(substitution, deg) } - this[newDegs] = if (newDegs !in this) newC else this[newDegs]!! + newC + putOrChange(newDegs, newC) { it -> it + newC } } } ) @@ -158,8 +158,7 @@ public fun NumberedPolynomial.substitute(args: Buffer): Numbered val deg = degs[variable] if (deg == 0u) product else product * args[variable].pow(deg.toInt()) } - if (newDegs !in this) this[newDegs] = newC - else this[newDegs] = this[newDegs]!! + newC + putOrChange(newDegs, newC) { it -> it + newC } } } ) @@ -183,8 +182,7 @@ public fun NumberedPolynomial.substitute(ring: Ring, args: Buffer): val deg = degs[variable] if (deg == 0u) product else product * power(args[variable], deg) } - if (newDegs !in this) this[newDegs] = newC - else this[newDegs] = this[newDegs]!! + newC + putOrChange(newDegs, newC) { it -> it + newC } } } ) 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 index f9a5a041b..1815749ce 100644 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt @@ -23,8 +23,8 @@ class NumberedConstructorsTest { ), Int.algebra.numberedPolynomialSpace { NumberedPolynomialDSL1 { - 5 { 1 pow 2u; 3 pow 3u } - (-6) { 2 pow 1u } + 5 { 0 pow 2u; 2 pow 3u } + (-6) { 1 pow 1u } } }, "test 1" @@ -47,8 +47,8 @@ class NumberedConstructorsTest { ), Int.algebra.numberedPolynomialSpace { NumberedPolynomialDSL1 { - 5 { 1 pow 1u; 1 pow 1u } - (-6) { 1 pow 2u } + 5 { 0 pow 1u; 0 pow 1u } + (-6) { 0 pow 2u } } }, "test 3" @@ -59,8 +59,8 @@ class NumberedConstructorsTest { ), Int.algebra.numberedPolynomialSpace { NumberedPolynomialDSL1 { - 5 { 1 pow 1u; 1 pow 1u } - (-6) { 1 pow 2u; 3 pow 0u } + 5 { 0 pow 1u; 0 pow 1u } + (-6) { 0 pow 2u; 2 pow 0u } } }, "test 3" -- 2.34.1 From 3eef778f6036baa375d40be4f71f697ca707c5ea Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 16 Jul 2022 16:27:11 +0300 Subject: [PATCH 143/275] Add mandatory MutableBufferFactory to Algebra #477 --- CHANGELOG.md | 1 + .../kscience/kmath/benchmarks/DotBenchmark.kt | 3 +- .../kmath/benchmarks/NDFieldBenchmark.kt | 10 +--- .../kmath/benchmarks/ViktorBenchmark.kt | 21 +++---- .../kmath/benchmarks/ViktorLogBenchmark.kt | 7 +-- .../kscience/kmath/operations/complexDemo.kt | 5 +- .../kscience/kmath/structures/NDField.kt | 21 ++----- .../space/kscience/kmath/complex/Complex.kt | 8 +-- .../kscience/kmath/complex/ComplexFieldND.kt | 5 -- .../kscience/kmath/expressions/DSAlgebra.kt | 42 +++++++------- .../kmath/linear/BufferedLinearSpace.kt | 7 +-- .../kscience/kmath/linear/LinearSpace.kt | 16 +----- .../kscience/kmath/nd/BufferAlgebraND.kt | 10 ++-- .../space/kscience/kmath/nd/StructureND.kt | 4 +- .../kscience/kmath/operations/Algebra.kt | 13 +++-- .../space/kscience/kmath/operations/BigInt.kt | 13 +---- .../kmath/operations/BufferAlgebra.kt | 47 +++++++-------- .../kmath/operations/DoubleBufferOps.kt | 4 +- .../kmath/operations/bufferOperation.kt | 4 +- .../kscience/kmath/operations/numbers.kt | 33 +++++------ .../space/kscience/kmath/structures/Buffer.kt | 18 +++++- .../kscience/kmath/structures/ByteBuffer.kt | 57 +++++++++++++++++++ .../kscience/kmath/expressions/DSTest.kt | 2 +- .../histogram/UniformHistogramGroupND.kt | 14 ++--- .../space/kscience/kmath/stat/Sampler.kt | 2 +- 25 files changed, 187 insertions(+), 180 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ByteBuffer.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index ec993fb36..4852f474a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## [Unreleased] ### Added - Autodiff for generic algebra elements in core! +- Algebra now has an obligatory `bufferFactory` (#477). ### Changed - Kotlin 1.7 diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt index 7d5ae310b..7ceecb5ab 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt @@ -16,7 +16,6 @@ import space.kscience.kmath.linear.linearSpace import space.kscience.kmath.multik.multikAlgebra import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.invoke -import space.kscience.kmath.structures.Buffer import space.kscience.kmath.tensorflow.produceWithTF import space.kscience.kmath.tensors.core.DoubleTensorAlgebra import space.kscience.kmath.tensors.core.tensorAlgebra @@ -84,7 +83,7 @@ internal class DotBenchmark { } @Benchmark - fun bufferedDot(blackhole: Blackhole) = with(DoubleField.linearSpace(Buffer.Companion::auto)) { + fun bufferedDot(blackhole: Blackhole) = with(DoubleField.linearSpace) { blackhole.consume(matrix1 dot matrix2) } diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt index e3b3dde05..89673acd4 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt @@ -20,7 +20,6 @@ import space.kscience.kmath.nd.ndAlgebra import space.kscience.kmath.nd.one import space.kscience.kmath.nd4j.nd4j import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.structures.Buffer import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.one import space.kscience.kmath.tensors.core.tensorAlgebra @@ -28,12 +27,6 @@ import space.kscience.kmath.viktor.viktorAlgebra @State(Scope.Benchmark) internal class NDFieldBenchmark { - @Benchmark - fun autoFieldAdd(blackhole: Blackhole) = with(autoField) { - var res: StructureND = one(shape) - repeat(n) { res += 1.0 } - blackhole.consume(res) - } @Benchmark fun specializedFieldAdd(blackhole: Blackhole) = with(specializedField) { @@ -95,9 +88,8 @@ internal class NDFieldBenchmark { private const val dim = 1000 private const val n = 100 private val shape = intArrayOf(dim, dim) - private val autoField = BufferedFieldOpsND(DoubleField, Buffer.Companion::auto) private val specializedField = DoubleField.ndAlgebra - private val genericField = BufferedFieldOpsND(DoubleField, Buffer.Companion::boxing) + private val genericField = BufferedFieldOpsND(DoubleField) private val nd4jField = DoubleField.nd4j private val multikField = DoubleField.multikAlgebra private val viktorField = DoubleField.viktorAlgebra diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt index de301678c..0e92a703e 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt @@ -10,25 +10,19 @@ import kotlinx.benchmark.Blackhole import kotlinx.benchmark.Scope import kotlinx.benchmark.State import org.jetbrains.bio.viktor.F64Array -import space.kscience.kmath.nd.* +import space.kscience.kmath.nd.Shape +import space.kscience.kmath.nd.StructureND +import space.kscience.kmath.nd.ndAlgebra +import space.kscience.kmath.nd.one import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.structures.Buffer import space.kscience.kmath.viktor.ViktorFieldND @State(Scope.Benchmark) internal class ViktorBenchmark { - @Benchmark - fun automaticFieldAddition(blackhole: Blackhole) { - with(autoField) { - var res: StructureND = one(shape) - repeat(n) { res += 1.0 } - blackhole.consume(res) - } - } @Benchmark - fun realFieldAddition(blackhole: Blackhole) { - with(realField) { + fun doubleFieldAddition(blackhole: Blackhole) { + with(doubleField) { var res: StructureND = one(shape) repeat(n) { res += 1.0 } blackhole.consume(res) @@ -58,8 +52,7 @@ internal class ViktorBenchmark { private val shape = Shape(dim, dim) // automatically build context most suited for given type. - private val autoField = BufferedFieldOpsND(DoubleField, Buffer.Companion::auto) - private val realField = DoubleField.ndAlgebra + private val doubleField = DoubleField.ndAlgebra private val viktorField = ViktorFieldND(dim, dim) } } diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt index dfdd89d74..7bb0b876e 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt @@ -10,19 +10,17 @@ import kotlinx.benchmark.Blackhole import kotlinx.benchmark.Scope import kotlinx.benchmark.State import org.jetbrains.bio.viktor.F64Array -import space.kscience.kmath.nd.BufferedFieldOpsND import space.kscience.kmath.nd.Shape import space.kscience.kmath.nd.ndAlgebra import space.kscience.kmath.nd.one import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.structures.Buffer import space.kscience.kmath.viktor.ViktorFieldND @State(Scope.Benchmark) internal class ViktorLogBenchmark { @Benchmark fun realFieldLog(blackhole: Blackhole) { - with(realField) { + with(doubleField) { val fortyTwo = structureND(shape) { 42.0 } var res = one(shape) repeat(n) { res = ln(fortyTwo) } @@ -54,8 +52,7 @@ internal class ViktorLogBenchmark { private val shape = Shape(dim, dim) // automatically build context most suited for given type. - private val autoField = BufferedFieldOpsND(DoubleField, Buffer.Companion::auto) - private val realField = DoubleField.ndAlgebra + private val doubleField = DoubleField.ndAlgebra private val viktorField = ViktorFieldND(dim, dim) } } diff --git a/examples/src/main/kotlin/space/kscience/kmath/operations/complexDemo.kt b/examples/src/main/kotlin/space/kscience/kmath/operations/complexDemo.kt index 2e1801cc2..285b8d000 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/operations/complexDemo.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/operations/complexDemo.kt @@ -7,7 +7,6 @@ package space.kscience.kmath.operations import space.kscience.kmath.complex.Complex import space.kscience.kmath.complex.algebra -import space.kscience.kmath.complex.bufferAlgebra import space.kscience.kmath.complex.ndAlgebra import space.kscience.kmath.nd.BufferND import space.kscience.kmath.nd.StructureND @@ -18,7 +17,7 @@ fun main() = Complex.algebra { println(complex * 8 - 5 * i) //flat buffer - val buffer = with(bufferAlgebra){ + val buffer = with(bufferAlgebra) { buffer(8) { Complex(it, -it) }.map { Complex(it.im, it.re) } } println(buffer) @@ -30,7 +29,7 @@ fun main() = Complex.algebra { println(element) // 1d element operation - val result: StructureND = ndAlgebra{ + val result: StructureND = ndAlgebra { val a = structureND(8) { (it) -> i * it - it.toDouble() } val b = 3 val c = Complex(1.0, 1.0) diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt index b680e267d..d6ff1dceb 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt @@ -32,12 +32,10 @@ fun main() { val shape = Shape(dim, dim) - // automatically build context most suited for given type. - val autoField = BufferedFieldOpsND(DoubleField, Buffer.Companion::auto) // specialized nd-field for Double. It works as generic Double field as well. - val realField = DoubleField.ndAlgebra - //A generic boxing field. It should be used for objects, not primitives. - val boxingField = BufferedFieldOpsND(DoubleField, Buffer.Companion::boxing) + val doubleField = DoubleField.ndAlgebra + //A generic field. It should be used for objects, not primitives. + val genericField = BufferedFieldOpsND(DoubleField) // Nd4j specialized field. val nd4jField = DoubleField.nd4j //viktor field @@ -46,14 +44,14 @@ fun main() { val parallelField = DoubleField.ndStreaming(dim, dim) measureAndPrint("Boxing addition") { - boxingField { + genericField { var res: StructureND = one(shape) repeat(n) { res += 1.0 } } } measureAndPrint("Specialized addition") { - realField { + doubleField { var res: StructureND = one(shape) repeat(n) { res += 1.0 } } @@ -80,15 +78,8 @@ fun main() { } } - measureAndPrint("Automatic field addition") { - autoField { - var res: StructureND = one(shape) - repeat(n) { res += 1.0 } - } - } - measureAndPrint("Lazy addition") { - val res = realField.one(shape).mapAsync(GlobalScope) { + val res = doubleField.one(shape).mapAsync(GlobalScope) { var c = 0.0 repeat(n) { c += 1.0 diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt index 77fe782a9..f56fb0f6e 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 @@ -10,10 +10,7 @@ import space.kscience.kmath.memory.MemorySpec import space.kscience.kmath.memory.MemoryWriter import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* -import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.MemoryBuffer -import space.kscience.kmath.structures.MutableBuffer -import space.kscience.kmath.structures.MutableMemoryBuffer +import space.kscience.kmath.structures.* import kotlin.math.* /** @@ -54,6 +51,9 @@ public object ComplexField : Norm, NumbersAddOps, ScaleOperations { + override val bufferFactory: MutableBufferFactory = MutableBufferFactory { size, init -> + MutableMemoryBuffer.create(Complex, size, init) + } override val zero: Complex = 0.0.toComplex() override val one: Complex = 1.0.toComplex() diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt index 46d4b7c5c..65943f421 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 @@ -56,11 +56,6 @@ public sealed class ComplexFieldOpsND : BufferedFieldOpsND - get() = bufferAlgebra(Buffer.Companion::complex) - - @OptIn(UnstableKMathAPI::class) public class ComplexFieldND(override val shape: Shape) : ComplexFieldOpsND(), FieldND, diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DSAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DSAlgebra.kt index 59e6f4f6f..c55e41bb2 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 @@ -78,9 +78,9 @@ public val > DS.value: T get() = data[0] @UnstableKMathAPI public abstract class DSAlgebra>( public val algebra: A, - public val bufferFactory: MutableBufferFactory, public val order: Int, bindings: Map, + public val valueBufferFactory: MutableBufferFactory = algebra.bufferFactory, ) : ExpressionAlgebra>, SymbolIndexer { /** @@ -90,6 +90,7 @@ public abstract class DSAlgebra>( */ @PublishedApi internal val compiler: DSCompiler by lazy { + val numberOfVariables = bindings.size // get the cached compilers val cache: Array?>>? = null @@ -115,7 +116,7 @@ public abstract class DSAlgebra>( newCache[p][o] = DSCompiler( algebra, - bufferFactory, + valueBufferFactory, p, o, valueCompiler, @@ -139,16 +140,13 @@ public abstract class DSAlgebra>( } override val symbols: List = bindings.map { it.key } - public val numberOfVariables: Int get() = symbols.size - - private fun bufferForVariable(index: Int, value: T): Buffer { - val buffer = bufferFactory(compiler.size) { algebra.zero } + val buffer = valueBufferFactory(compiler.size) { algebra.zero } buffer[0] = value if (compiler.order > 0) { // the derivative of the variable with respect to itself is 1. - val indexOfDerivative = compiler.getPartialDerivativeIndex(*IntArray(numberOfVariables).apply { + val indexOfDerivative = compiler.getPartialDerivativeIndex(*IntArray(symbols.size).apply { set(index, 1) }) @@ -209,7 +207,7 @@ public abstract class DSAlgebra>( } public override fun const(value: T): DS { - val buffer = bufferFactory(compiler.size) { algebra.zero } + val buffer = valueBufferFactory(compiler.size) { algebra.zero } buffer[0] = value return DS(buffer) @@ -245,10 +243,10 @@ public abstract class DSAlgebra>( @UnstableKMathAPI public open class DSRing( algebra: A, - bufferFactory: MutableBufferFactory, order: Int, bindings: Map, -) : DSAlgebra(algebra, bufferFactory, order, bindings), + valueBufferFactory: MutableBufferFactory, +) : DSAlgebra(algebra, order, bindings, valueBufferFactory), Ring>, ScaleOperations>, NumericAlgebra>, NumbersAddOps> where A : Ring, A : NumericAlgebra, A : ScaleOperations { @@ -263,14 +261,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 = bufferFactory(compiler.size) { data[it] } + val newData = valueBufferFactory(compiler.size) { data[it] } algebra.block(newData) return DS(newData) } protected fun DS.mapData(block: A.(T) -> T): DS { require(derivativeAlgebra == this@DSRing) { "All derivative operations should be done in the same algebra" } - val newData: Buffer = data.map(bufferFactory) { + val newData: Buffer = data.map(valueBufferFactory) { algebra.block(it) } return DS(newData) @@ -278,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(bufferFactory, block) + val newData: Buffer = data.mapIndexed(valueBufferFactory, block) return DS(newData) } @@ -327,19 +325,19 @@ public open class DSRing( @UnstableKMathAPI public class DerivativeStructureRingExpression( public val algebra: A, - public val bufferFactory: MutableBufferFactory, + public val elementBufferFactory: MutableBufferFactory = algebra.bufferFactory, public val function: DSRing.() -> DS, ) : DifferentiableExpression where A : Ring, A : ScaleOperations, A : NumericAlgebra { override operator fun invoke(arguments: Map): T = - DSRing(algebra, bufferFactory, 0, arguments).function().value + DSRing(algebra, 0, arguments, elementBufferFactory).function().value override fun derivativeOrNull(symbols: List): Expression = Expression { arguments -> with( DSRing( algebra, - bufferFactory, symbols.size, - arguments + arguments, + elementBufferFactory ) ) { function().derivative(symbols) } } @@ -354,10 +352,10 @@ public class DerivativeStructureRingExpression( @UnstableKMathAPI public class DSField>( algebra: A, - bufferFactory: MutableBufferFactory, order: Int, bindings: Map, -) : DSRing(algebra, bufferFactory, order, bindings), ExtendedField> { + valueBufferFactory: MutableBufferFactory, +) : DSRing(algebra, order, bindings, valueBufferFactory), ExtendedField> { override fun number(value: Number): DS = const(algebra.number(value)) override fun divide(left: DS, right: DS): DS = left.transformDataBuffer { result -> @@ -441,18 +439,18 @@ public class DSField>( @UnstableKMathAPI public class DSFieldExpression>( public val algebra: A, - public val bufferFactory: MutableBufferFactory, + private val valueBufferFactory: MutableBufferFactory = algebra.bufferFactory, public val function: DSField.() -> DS, ) : DifferentiableExpression { override operator fun invoke(arguments: Map): T = - DSField(algebra, bufferFactory, 0, arguments).function().value + DSField(algebra, 0, arguments, valueBufferFactory).function().value override fun derivativeOrNull(symbols: List): Expression = Expression { arguments -> DSField( algebra, - bufferFactory, symbols.size, arguments, + valueBufferFactory, ).run { function().derivative(symbols) } } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt index 36cbd9064..8f7569699 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 @@ -11,13 +11,12 @@ import space.kscience.kmath.nd.as2D import space.kscience.kmath.nd.asND import space.kscience.kmath.operations.* import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.VirtualBuffer import space.kscience.kmath.structures.indices public class BufferedLinearSpace>( - private val bufferAlgebra: BufferAlgebra + private val bufferAlgebra: BufferAlgebra, ) : LinearSpace { override val elementAlgebra: A get() = bufferAlgebra.elementAlgebra @@ -91,5 +90,5 @@ public class BufferedLinearSpace>( } -public fun > A.linearSpace(bufferFactory: BufferFactory): BufferedLinearSpace = - BufferedLinearSpace(BufferRingOps(this, bufferFactory)) +public val > A.linearSpace: BufferedLinearSpace + get() = BufferedLinearSpace(BufferRingOps(this)) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt index 10438dd02..d437070c9 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt @@ -11,12 +11,9 @@ import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.nd.StructureFeature import space.kscience.kmath.nd.as1D import space.kscience.kmath.operations.BufferRingOps -import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.BufferFactory -import space.kscience.kmath.structures.DoubleBuffer import kotlin.reflect.KClass /** @@ -187,18 +184,9 @@ public interface LinearSpace> { * A structured matrix with custom buffer */ public fun > buffered( - algebra: A, - bufferFactory: BufferFactory = BufferFactory(Buffer.Companion::boxing), - ): LinearSpace = BufferedLinearSpace(BufferRingOps(algebra, bufferFactory)) + algebra: A + ): LinearSpace = BufferedLinearSpace(BufferRingOps(algebra)) - @Deprecated("use DoubleField.linearSpace") - public val double: LinearSpace = buffered(DoubleField, ::DoubleBuffer) - - /** - * Automatic buffered matrix, unboxed if it is possible - */ - public inline fun > auto(ring: A): LinearSpace = - buffered(ring, Buffer.Companion::auto) } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt index 68e8ebe90..8c5eef3d0 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 @@ -10,7 +10,6 @@ package space.kscience.kmath.nd import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* -import space.kscience.kmath.structures.BufferFactory public interface BufferAlgebraND> : AlgebraND { public val indexerBuilder: (IntArray) -> ShapeIndexer @@ -60,7 +59,7 @@ public inline fun > BufferAlgebraND.mapInline( return BufferND( indexes, bufferAlgebra.run { - bufferFactory(buffer.size) { elementAlgebra.transform(buffer[it]) } + elementBufferFactory(buffer.size) { elementAlgebra.transform(buffer[it]) } } ) } @@ -74,7 +73,7 @@ internal inline fun > BufferAlgebraND.mapIndexedInline( return BufferND( indexes, bufferAlgebra.run { - bufferFactory(buffer.size) { elementAlgebra.transform(indexes.index(it), buffer[it]) } + elementBufferFactory(buffer.size) { elementAlgebra.transform(indexes.index(it), buffer[it]) } } ) } @@ -91,7 +90,7 @@ internal inline fun > BufferAlgebraND.zipInline( return BufferND( indexes, bufferAlgebra.run { - bufferFactory(lbuffer.size) { elementAlgebra.block(lbuffer[it], rbuffer[it]) } + elementBufferFactory(lbuffer.size) { elementAlgebra.block(lbuffer[it], rbuffer[it]) } } ) } @@ -116,9 +115,8 @@ public open class BufferedFieldOpsND>( public constructor( elementAlgebra: A, - bufferFactory: BufferFactory, indexerBuilder: (IntArray) -> ShapeIndexer = BufferAlgebraND.defaultIndexerBuilder, - ) : this(BufferFieldOps(elementAlgebra, bufferFactory), indexerBuilder) + ) : this(BufferFieldOps(elementAlgebra), indexerBuilder) @OptIn(PerformancePitfall::class) override fun scale(a: StructureND, value: Double): StructureND = a.map { it * value } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt index 6e54e1b9d..e14b8bf9d 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 @@ -120,7 +120,7 @@ public interface StructureND : Featured, WithShape { */ public fun buffered( strides: Strides, - bufferFactory: BufferFactory = BufferFactory(Buffer.Companion::boxing), + bufferFactory: BufferFactory = BufferFactory.boxing(), initializer: (IntArray) -> T, ): BufferND = BufferND(strides, bufferFactory(strides.linearSize) { i -> initializer(strides.index(i)) }) @@ -140,7 +140,7 @@ public interface StructureND : Featured, WithShape { public fun buffered( shape: IntArray, - bufferFactory: BufferFactory = BufferFactory(Buffer.Companion::boxing), + bufferFactory: BufferFactory = BufferFactory.boxing(), initializer: (IntArray) -> T, ): BufferND = buffered(DefaultStrides(shape), bufferFactory, initializer) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt index 45ba32c13..a93b4365e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt @@ -8,12 +8,7 @@ package space.kscience.kmath.operations import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Ring.Companion.optimizedPower - -/** - * Stub for DSL the [Algebra] is. - */ -@DslMarker -public annotation class KMathContext +import space.kscience.kmath.structures.MutableBufferFactory /** * Represents an algebraic structure. @@ -21,6 +16,12 @@ public annotation class KMathContext * @param T the type of element of this structure. */ public interface Algebra { + + /** + * Provide a factory for buffers, associated with this [Algebra] + */ + public val bufferFactory: MutableBufferFactory get() = MutableBufferFactory.boxing() + /** * Wraps a raw string to [T] object. This method is designed for three purposes: * diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt index 99268348b..9b6911f73 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt @@ -10,7 +10,6 @@ import space.kscience.kmath.nd.BufferedRingOpsND import space.kscience.kmath.operations.BigInt.Companion.BASE import space.kscience.kmath.operations.BigInt.Companion.BASE_SIZE import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.MutableBuffer import kotlin.math.log2 import kotlin.math.max import kotlin.math.min @@ -528,19 +527,11 @@ public fun String.parseBigInteger(): BigInt? { public val BigInt.algebra: BigIntField get() = BigIntField -@Deprecated("Use BigInt::buffer") -public inline fun Buffer.Companion.bigInt(size: Int, initializer: (Int) -> BigInt): Buffer = - boxing(size, initializer) - public inline fun BigInt.Companion.buffer(size: Int, initializer: (Int) -> BigInt): Buffer = Buffer.boxing(size, initializer) -@Deprecated("Use BigInt::mutableBuffer") -public inline fun MutableBuffer.Companion.bigInt(size: Int, initializer: (Int) -> BigInt): MutableBuffer = - boxing(size, initializer) - -public inline fun BigInt.mutableBuffer(size: Int, initializer: (Int) -> BigInt): Buffer = +public inline fun BigInt.Companion.mutableBuffer(size: Int, initializer: (Int) -> BigInt): Buffer = Buffer.boxing(size, initializer) public val BigIntField.nd: BufferedRingOpsND - get() = BufferedRingOpsND(BufferRingOps(BigIntField, BigInt::buffer)) + get() = BufferedRingOpsND(BufferRingOps(BigIntField)) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BufferAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BufferAlgebra.kt index 51fff8b69..a256fe7d1 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 @@ -7,8 +7,6 @@ package space.kscience.kmath.operations import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory -import space.kscience.kmath.structures.DoubleBuffer -import space.kscience.kmath.structures.ShortBuffer public interface WithSize { public val size: Int @@ -19,11 +17,11 @@ public interface WithSize { */ public interface BufferAlgebra> : Algebra> { public val elementAlgebra: A - public val bufferFactory: BufferFactory + public val elementBufferFactory: BufferFactory get() = elementAlgebra.bufferFactory public fun buffer(size: Int, vararg elements: T): Buffer { require(elements.size == size) { "Expected $size elements but found ${elements.size}" } - return bufferFactory(size) { elements[it] } + return elementBufferFactory(size) { elements[it] } } //TODO move to multi-receiver inline extension @@ -36,13 +34,13 @@ public interface BufferAlgebra> : Algebra> { override fun unaryOperationFunction(operation: String): (arg: Buffer) -> Buffer { val operationFunction = elementAlgebra.unaryOperationFunction(operation) - return { arg -> bufferFactory(arg.size) { operationFunction(arg[it]) } } + return { arg -> elementBufferFactory(arg.size) { operationFunction(arg[it]) } } } override fun binaryOperationFunction(operation: String): (left: Buffer, right: Buffer) -> Buffer { val operationFunction = elementAlgebra.binaryOperationFunction(operation) return { left, right -> - bufferFactory(left.size) { operationFunction(left[it], right[it]) } + elementBufferFactory(left.size) { operationFunction(left[it], right[it]) } } } } @@ -53,7 +51,7 @@ public interface BufferAlgebra> : Algebra> { private inline fun > BufferAlgebra.mapInline( buffer: Buffer, crossinline block: A.(T) -> T, -): Buffer = bufferFactory(buffer.size) { elementAlgebra.block(buffer[it]) } +): Buffer = elementBufferFactory(buffer.size) { elementAlgebra.block(buffer[it]) } /** * Inline map @@ -61,7 +59,7 @@ private inline fun > BufferAlgebra.mapInline( private inline fun > BufferAlgebra.mapIndexedInline( buffer: Buffer, crossinline block: A.(index: Int, arg: T) -> T, -): Buffer = bufferFactory(buffer.size) { elementAlgebra.block(it, buffer[it]) } +): Buffer = elementBufferFactory(buffer.size) { elementAlgebra.block(it, buffer[it]) } /** * Inline zip @@ -72,15 +70,15 @@ private inline fun > BufferAlgebra.zipInline( crossinline block: A.(l: T, r: T) -> T, ): Buffer { require(l.size == r.size) { "Incompatible buffer sizes. left: ${l.size}, right: ${r.size}" } - return bufferFactory(l.size) { elementAlgebra.block(l[it], r[it]) } + return elementBufferFactory(l.size) { elementAlgebra.block(l[it], r[it]) } } public fun BufferAlgebra.buffer(size: Int, initializer: (Int) -> T): Buffer { - return bufferFactory(size, initializer) + return elementBufferFactory(size, initializer) } public fun A.buffer(initializer: (Int) -> T): Buffer where A : BufferAlgebra, A : WithSize { - return bufferFactory(size, initializer) + return elementBufferFactory(size, initializer) } public fun > BufferAlgebra.sin(arg: Buffer): Buffer = @@ -131,7 +129,6 @@ public fun > BufferAlgebra.pow(arg: Buffer, p public open class BufferRingOps>( override val elementAlgebra: A, - override val bufferFactory: BufferFactory, ) : BufferAlgebra, RingOps> { override fun add(left: Buffer, right: Buffer): Buffer = zipInline(left, right) { l, r -> l + r } @@ -146,15 +143,13 @@ public open class BufferRingOps>( } public val ShortRing.bufferAlgebra: BufferRingOps - get() = BufferRingOps(ShortRing, ::ShortBuffer) + get() = BufferRingOps(ShortRing) public open class BufferFieldOps>( elementAlgebra: A, - bufferFactory: BufferFactory, -) : BufferRingOps(elementAlgebra, bufferFactory), BufferAlgebra, FieldOps>, - ScaleOperations> { +) : BufferRingOps(elementAlgebra), BufferAlgebra, FieldOps>, ScaleOperations> { -// override fun add(left: Buffer, right: Buffer): Buffer = zipInline(left, right) { l, r -> l + r } + // override fun add(left: Buffer, right: Buffer): Buffer = zipInline(left, right) { l, r -> l + r } // override fun multiply(left: Buffer, right: Buffer): Buffer = zipInline(left, right) { l, r -> l * r } override fun divide(left: Buffer, right: Buffer): Buffer = zipInline(left, right) { l, r -> l / r } @@ -167,30 +162,26 @@ public open class BufferFieldOps>( public class BufferField>( elementAlgebra: A, - bufferFactory: BufferFactory, override val size: Int, -) : BufferFieldOps(elementAlgebra, bufferFactory), Field>, WithSize { +) : BufferFieldOps(elementAlgebra), Field>, WithSize { - override val zero: Buffer = bufferFactory(size) { elementAlgebra.zero } - override val one: Buffer = bufferFactory(size) { elementAlgebra.one } + override val zero: Buffer = elementAlgebra.bufferFactory(size) { elementAlgebra.zero } + override val one: Buffer = elementAlgebra.bufferFactory(size) { elementAlgebra.one } } /** * Generate full buffer field from given buffer operations */ public fun > BufferFieldOps.withSize(size: Int): BufferField = - BufferField(elementAlgebra, bufferFactory, size) + BufferField(elementAlgebra, size) //Double buffer specialization public fun BufferField.buffer(vararg elements: Number): Buffer { require(elements.size == size) { "Expected $size elements but found ${elements.size}" } - return bufferFactory(size) { elements[it].toDouble() } + return elementBufferFactory(size) { elements[it].toDouble() } } -public fun > A.bufferAlgebra(bufferFactory: BufferFactory): BufferFieldOps = - BufferFieldOps(this, bufferFactory) - -public val DoubleField.bufferAlgebra: BufferFieldOps - get() = BufferFieldOps(DoubleField, ::DoubleBuffer) +public val > A.bufferAlgebra: BufferFieldOps + get() = BufferFieldOps(this) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/DoubleBufferOps.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/DoubleBufferOps.kt index 083892105..669c0a390 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,8 +7,8 @@ package space.kscience.kmath.operations import space.kscience.kmath.linear.Point import space.kscience.kmath.structures.Buffer -import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.structures.MutableBufferFactory import space.kscience.kmath.structures.asBuffer import kotlin.math.* @@ -19,7 +19,7 @@ public abstract class DoubleBufferOps : BufferAlgebra, Exte Norm, Double> { override val elementAlgebra: DoubleField get() = DoubleField - override val bufferFactory: BufferFactory get() = BufferFactory(::DoubleBuffer) + override val elementBufferFactory: MutableBufferFactory get() = elementAlgebra.bufferFactory override fun Buffer.map(block: DoubleField.(Double) -> Double): DoubleBuffer = mapInline { DoubleField.block(it) } 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 652472fcf..0beda11a5 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 @@ -88,7 +88,7 @@ public inline fun Buffer.mapIndexed( */ public inline fun Buffer.mapIndexed( crossinline block: (index: Int, value: T) -> R, -): Buffer = BufferFactory(Buffer.Companion::auto).invoke(size) { block(it, get(it)) } +): Buffer = Buffer.auto(size) { block(it, get(it)) } /** * Fold given buffer according to [operation] @@ -105,7 +105,7 @@ public inline fun Buffer.fold(initial: R, operation: (acc: R, T) -> R) @UnstableKMathAPI public inline fun Buffer.zip( other: Buffer, - bufferFactory: BufferFactory = BufferFactory(Buffer.Companion::auto), + bufferFactory: BufferFactory = BufferFactory.auto(), crossinline transform: (T1, T2) -> R, ): Buffer { require(size == other.size) { "Buffer size mismatch in zip: expected $size but found ${other.size}" } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt index 07a137415..c108aa729 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.operations +import space.kscience.kmath.structures.* import kotlin.math.pow as kpow /** @@ -65,6 +66,8 @@ public interface ExtendedField : ExtendedFieldOps, Field, PowerOperatio */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public object DoubleField : ExtendedField, Norm, ScaleOperations { + override val bufferFactory: MutableBufferFactory = MutableBufferFactory(::DoubleBuffer) + override inline val zero: Double get() = 0.0 override inline val one: Double get() = 1.0 @@ -123,6 +126,8 @@ public val Double.Companion.algebra: DoubleField get() = DoubleField */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public object FloatField : ExtendedField, Norm { + override val bufferFactory: MutableBufferFactory = MutableBufferFactory(::FloatBuffer) + override inline val zero: Float get() = 0.0f override inline val one: Float get() = 1.0f @@ -177,11 +182,10 @@ public val Float.Companion.algebra: FloatField get() = FloatField */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public object IntRing : Ring, Norm, NumericAlgebra { - override inline val zero: Int - get() = 0 + override val bufferFactory: MutableBufferFactory = MutableBufferFactory(::IntBuffer) - override inline val one: Int - get() = 1 + override inline val zero: Int get() = 0 + override inline val one: Int get() = 1 override fun number(value: Number): Int = value.toInt() override inline fun add(left: Int, right: Int): Int = left + right @@ -201,11 +205,10 @@ public val Int.Companion.algebra: IntRing get() = IntRing */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public object ShortRing : Ring, Norm, NumericAlgebra { - override inline val zero: Short - get() = 0 + override val bufferFactory: MutableBufferFactory = MutableBufferFactory(::ShortBuffer) - override inline val one: Short - get() = 1 + override inline val zero: Short get() = 0 + override inline val one: Short get() = 1 override fun number(value: Number): Short = value.toShort() override inline fun add(left: Short, right: Short): Short = (left + right).toShort() @@ -225,11 +228,10 @@ public val Short.Companion.algebra: ShortRing get() = ShortRing */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public object ByteRing : Ring, Norm, NumericAlgebra { - override inline val zero: Byte - get() = 0 + override val bufferFactory: MutableBufferFactory = MutableBufferFactory(::ByteBuffer) - override inline val one: Byte - get() = 1 + override inline val zero: Byte get() = 0 + override inline val one: Byte get() = 1 override fun number(value: Number): Byte = value.toByte() override inline fun add(left: Byte, right: Byte): Byte = (left + right).toByte() @@ -249,11 +251,10 @@ public val Byte.Companion.algebra: ByteRing get() = ByteRing */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") public object LongRing : Ring, Norm, NumericAlgebra { - override inline val zero: Long - get() = 0L + override val bufferFactory: MutableBufferFactory = MutableBufferFactory(::LongBuffer) - override inline val one: Long - get() = 1L + override inline val zero: Long get() = 0L + override inline val one: Long get() = 1L override fun number(value: Number): Long = value.toLong() override inline fun add(left: Long, right: Long): Long = left + right diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt index 1c79c257a..5757848fe 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 @@ -16,6 +16,14 @@ import kotlin.reflect.KClass */ public fun interface BufferFactory { public operator fun invoke(size: Int, builder: (Int) -> T): Buffer + + public companion object{ + public inline fun auto(): BufferFactory = + BufferFactory(Buffer.Companion::auto) + + public fun boxing(): BufferFactory = + BufferFactory(Buffer.Companion::boxing) + } } /** @@ -23,8 +31,16 @@ public fun interface BufferFactory { * * @param T the type of buffer. */ -public fun interface MutableBufferFactory: BufferFactory{ +public fun interface MutableBufferFactory : BufferFactory { override fun invoke(size: Int, builder: (Int) -> T): MutableBuffer + + public companion object { + public inline fun auto(): MutableBufferFactory = + MutableBufferFactory(MutableBuffer.Companion::auto) + + public fun boxing(): MutableBufferFactory = + MutableBufferFactory(MutableBuffer.Companion::boxing) + } } /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ByteBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ByteBuffer.kt new file mode 100644 index 000000000..e7bf2b47c --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ByteBuffer.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.structures + +import kotlin.jvm.JvmInline + +/** + * Specialized [MutableBuffer] implementation over [ByteArray]. + * + * @property array the underlying array. + */ +@JvmInline +public value class ByteBuffer(public val array: ByteArray) : MutableBuffer { + override val size: Int get() = array.size + + override operator fun get(index: Int): Byte = array[index] + + override operator fun set(index: Int, value: Byte) { + array[index] = value + } + + override operator fun iterator(): ByteIterator = array.iterator() + override fun copy(): MutableBuffer = ByteBuffer(array.copyOf()) +} + +/** + * Creates a new [ByteBuffer] with the specified [size], where each element is calculated by calling the specified + * [init] function. + * + * The function [init] is called for each array element sequentially starting from the first one. + * It should return the value for a buffer element given its index. + */ +public inline fun ByteBuffer(size: Int, init: (Int) -> Byte): ByteBuffer = ByteBuffer(ByteArray(size) { init(it) }) + +/** + * Returns a new [ByteBuffer] of given elements. + */ +public fun ByteBuffer(vararg bytes: Byte): ByteBuffer = ByteBuffer(bytes) + +/** + * Returns a new [ByteArray] containing all the elements of this [Buffer]. + */ +public fun Buffer.toByteArray(): ByteArray = when (this) { + is ByteBuffer -> array.copyOf() + else -> ByteArray(size, ::get) +} + +/** + * Returns [ByteBuffer] over this array. + * + * @receiver the array. + * @return the new buffer. + */ +public fun ByteArray.asBuffer(): ByteBuffer = ByteBuffer(this) diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DSTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DSTest.kt index 727a918ec..b6581e503 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 @@ -22,7 +22,7 @@ internal inline fun diff( block: DSField.() -> Unit, ) { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - DSField(DoubleField, ::DoubleBuffer, order, mapOf(*parameters)).block() + DSField(DoubleField, order, mapOf(*parameters), ::DoubleBuffer).block() } internal class DSTest { 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 eafd55513..1ead049e6 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 @@ -21,14 +21,14 @@ public typealias HyperSquareBin = DomainBin /** * Multivariate histogram space for hyper-square real-field bins. - * @param bufferFactory is an optional parameter used to optimize buffer production. + * @param valueBufferFactory is an optional parameter used to optimize buffer production. */ public class UniformHistogramGroupND>( override val valueAlgebraND: FieldOpsND, private val lower: Buffer, private val upper: Buffer, private val binNums: IntArray = IntArray(lower.size) { 20 }, - private val bufferFactory: BufferFactory = BufferFactory(Buffer.Companion::boxing), + private val valueBufferFactory: BufferFactory = valueAlgebraND.elementAlgebra.bufferFactory, ) : HistogramGroupND { init { @@ -94,7 +94,7 @@ public class UniformHistogramGroupND>( } } hBuilder.apply(builder) - val values: BufferND = ndCounter.mapToBuffer(bufferFactory) { it.value } + val values: BufferND = ndCounter.mapToBuffer(valueBufferFactory) { it.value } return HistogramND(this, values) } @@ -114,12 +114,12 @@ public class UniformHistogramGroupND>( public fun > Histogram.Companion.uniformNDFromRanges( valueAlgebraND: FieldOpsND, vararg ranges: ClosedFloatingPointRange, - bufferFactory: BufferFactory = BufferFactory(Buffer.Companion::boxing), + bufferFactory: BufferFactory = valueAlgebraND.elementAlgebra.bufferFactory, ): UniformHistogramGroupND = UniformHistogramGroupND( valueAlgebraND, ranges.map(ClosedFloatingPointRange::start).asBuffer(), ranges.map(ClosedFloatingPointRange::endInclusive).asBuffer(), - bufferFactory = bufferFactory + valueBufferFactory = bufferFactory ) public fun Histogram.Companion.uniformDoubleNDFromRanges( @@ -140,7 +140,7 @@ public fun Histogram.Companion.uniformDoubleNDFromRanges( public fun > Histogram.Companion.uniformNDFromRanges( valueAlgebraND: FieldOpsND, vararg ranges: Pair, Int>, - bufferFactory: BufferFactory = BufferFactory(Buffer.Companion::boxing), + bufferFactory: BufferFactory = valueAlgebraND.elementAlgebra.bufferFactory, ): UniformHistogramGroupND = UniformHistogramGroupND( valueAlgebraND, ListBuffer( @@ -154,7 +154,7 @@ public fun > Histogram.Companion.uniformNDFromRanges( .map(ClosedFloatingPointRange::endInclusive) ), ranges.map(Pair, Int>::second).toIntArray(), - bufferFactory = bufferFactory + valueBufferFactory = bufferFactory ) public fun Histogram.Companion.uniformDoubleNDFromRanges( diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt index 890318e31..1c88922ac 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt @@ -35,7 +35,7 @@ public fun interface Sampler { public fun Sampler.sampleBuffer( generator: RandomGenerator, size: Int, - bufferFactory: BufferFactory = BufferFactory(Buffer.Companion::boxing), + bufferFactory: BufferFactory = BufferFactory.boxing(), ): Chain> { require(size > 1) //creating temporary storage once -- 2.34.1 From a1a2c41846b5a720cb05ec4bee9c5136c74b55c9 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sat, 16 Jul 2022 17:13:05 +0300 Subject: [PATCH 144/275] Add a bit more utilities for maps and refactor polynomials' code. --- .../LabeledPolynomial.kt | 100 ++++++++---------- .../NumberedPolynomial.kt | 100 +++++++----------- .../collectionUtils.kt | 39 ++++++- 3 files changed, 117 insertions(+), 122 deletions(-) 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 index b07674a1e..7df51930e 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/LabeledPolynomial.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/LabeledPolynomial.kt @@ -87,7 +87,7 @@ public class LabeledPolynomialSpace>( ) else LabeledPolynomialAsIs( mapOf(this@plus to 1U) to constantOne, - emptyMap() to constantOne * other, + emptyMap() to other.asConstant(), ) /** * Returns difference between the variable represented as a monic monomial and the integer represented as a constant polynomial. @@ -98,7 +98,7 @@ public class LabeledPolynomialSpace>( ) else LabeledPolynomialAsIs( mapOf(this@minus to 1U) to constantOne, - emptyMap() to constantOne * -other, + emptyMap() to (-other).asConstant(), ) /** * Returns product of the variable represented as a monic monomial and the integer represented as a constant polynomial. @@ -106,7 +106,7 @@ public class LabeledPolynomialSpace>( public override operator fun Symbol.times(other: Int): LabeledPolynomial = if (other == 0) zero else LabeledPolynomialAsIs( - mapOf(this to 1U) to constantOne * other, + mapOf(this to 1U) to other.asConstant(), ) /** @@ -118,7 +118,7 @@ public class LabeledPolynomialSpace>( ) else LabeledPolynomialAsIs( mapOf(other to 1U) to constantOne, - emptyMap() to constantOne * this@plus, + emptyMap() to this@plus.asConstant(), ) /** * Returns difference between the integer represented as a constant polynomial and the variable represented as a monic monomial. @@ -137,7 +137,7 @@ public class LabeledPolynomialSpace>( public override operator fun Int.times(other: Symbol): LabeledPolynomial = if (this == 0) zero else LabeledPolynomialAsIs( - mapOf(other to 1U) to constantOne * this@times, + mapOf(other to 1U) to this@times.asConstant(), ) /** @@ -146,11 +146,11 @@ public class LabeledPolynomialSpace>( * The operation is equivalent to adding [other] copies of unit polynomial to [this]. */ public override operator fun LabeledPolynomial.plus(other: Int): LabeledPolynomial = - if (other == 0) this - else with(coefficients) { - if (isEmpty()) other.asPolynomial() - else LabeledPolynomialAsIs( - withPutOrChanged(emptyMap(), other.asConstant()) { it -> it + other } + when { + other == 0 -> this + coefficients.isEmpty() -> other.asPolynomial() + else -> LabeledPolynomialAsIs( + coefficients.withPutOrChanged(emptyMap(), other.asConstant()) { it -> it + other } ) } /** @@ -159,11 +159,11 @@ public class LabeledPolynomialSpace>( * The operation is equivalent to subtraction [other] copies of unit polynomial from [this]. */ public override operator fun LabeledPolynomial.minus(other: Int): LabeledPolynomial = - if (other == 0) this - else with(coefficients) { - if (isEmpty()) (-other).asPolynomial() - else LabeledPolynomialAsIs( - withPutOrChanged(emptyMap(), (-other).asConstant()) { it -> it - other } + when { + other == 0 -> this + coefficients.isEmpty() -> other.asPolynomial() + else -> LabeledPolynomialAsIs( + coefficients.withPutOrChanged(emptyMap(), (-other).asConstant()) { it -> it - other } ) } /** @@ -186,11 +186,11 @@ public class LabeledPolynomialSpace>( * The operation is equivalent to adding [this] copies of unit polynomial to [other]. */ public override operator fun Int.plus(other: LabeledPolynomial): LabeledPolynomial = - if (this == 0) other - else with(other.coefficients) { - if (isEmpty()) this@plus.asPolynomial() - else LabeledPolynomialAsIs( - withPutOrChanged(emptyMap(), this@plus.asConstant()) { it -> this@plus + it } + when { + this == 0 -> other + other.coefficients.isEmpty() -> this@plus.asPolynomial() + else -> LabeledPolynomialAsIs( + other.coefficients.withPutOrChanged(emptyMap(), this@plus.asConstant()) { it -> this@plus + it } ) } /** @@ -275,12 +275,10 @@ public class LabeledPolynomialSpace>( * Returns sum of the constant represented as a polynomial and the polynomial. */ override operator fun C.plus(other: LabeledPolynomial): LabeledPolynomial = - with(other.coefficients) { - if (isEmpty()) this@plus.asLabeledPolynomial() - else LabeledPolynomialAsIs( - withPutOrChanged(emptyMap(), this@plus) { it -> this@plus + it } - ) - } + 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. */ @@ -304,22 +302,18 @@ public class LabeledPolynomialSpace>( * Returns sum of the constant represented as a polynomial and the polynomial. */ override operator fun LabeledPolynomial.plus(other: C): LabeledPolynomial = - with(coefficients) { - if (isEmpty()) other.asLabeledPolynomial() - else LabeledPolynomialAsIs( - withPutOrChanged(emptyMap(), other) { it -> it + other } - ) - } + 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 = - with(coefficients) { - if (isEmpty()) other.asLabeledPolynomial() - else LabeledPolynomialAsIs( - withPutOrChanged(emptyMap(), -other) { it -> it - other } - ) - } + 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. */ @@ -382,12 +376,10 @@ public class LabeledPolynomialSpace>( * Returns sum of the variable represented as a monic monomial and the polynomial. */ public override operator fun Symbol.plus(other: LabeledPolynomial): LabeledPolynomial = - with(other.coefficients) { - if (isEmpty()) this@plus.asPolynomial() - else LabeledPolynomialAsIs( - withPutOrChanged(mapOf(this@plus to 1U), constantOne) { it -> constantOne + it } - ) - } + 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. */ @@ -412,22 +404,18 @@ public class LabeledPolynomialSpace>( * Returns sum of the polynomial and the variable represented as a monic monomial. */ public override operator fun LabeledPolynomial.plus(other: Symbol): LabeledPolynomial = - with(coefficients) { - if (isEmpty()) other.asPolynomial() - else LabeledPolynomialAsIs( - withPutOrChanged(mapOf(other to 1U), constantOne) { it -> it + constantOne } - ) - } + 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 = - with(coefficients) { - if (isEmpty()) other.asPolynomial() - else LabeledPolynomialAsIs( - withPutOrChanged(mapOf(other to 1U), -constantOne) { it -> it - constantOne } - ) - } + 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. */ 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 index 14c03ff7c..037419cfc 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/NumberedPolynomial.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/NumberedPolynomial.kt @@ -69,10 +69,9 @@ public class NumberedPolynomialSpace>( */ public override operator fun NumberedPolynomial.plus(other: Int): NumberedPolynomial = if (other == 0) this - else - NumberedPolynomialAsIs( - coefficients.withPutOrChanged(emptyList(), other.asConstant()) { it -> it + other } - ) + else NumberedPolynomialAsIs( + coefficients.withPutOrChanged(emptyList(), other.asConstant()) { it -> it + other } + ) /** * Returns difference between the polynomial and the integer represented as a polynomial. * @@ -80,10 +79,9 @@ public class NumberedPolynomialSpace>( */ public override operator fun NumberedPolynomial.minus(other: Int): NumberedPolynomial = if (other == 0) this - else - NumberedPolynomialAsIs( - coefficients.withPutOrChanged(emptyList(), (-other).asConstant()) { it -> it - other } - ) + else NumberedPolynomialAsIs( + coefficients.withPutOrChanged(emptyList(), (-other).asConstant()) { it -> it - other } + ) /** * Returns product of the polynomial and the integer represented as a polynomial. * @@ -105,31 +103,25 @@ public class NumberedPolynomialSpace>( */ 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 } - ) + 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 = - NumberedPolynomialAsIs( - other.coefficients - .toMutableMap() - .apply { - if (this@minus == 0) { - forEach { (key, value) -> this[key] = -value } - } else { - forEach { (key, value) -> if (key.isNotEmpty()) this[key] = -value } - - val degs = emptyList() - - this[degs] = this@minus - getOrElse(degs) { constantZero } - } + 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. * @@ -148,29 +140,21 @@ public class NumberedPolynomialSpace>( * Returns sum of the constant represented as a polynomial and the polynomial. */ override operator fun C.plus(other: NumberedPolynomial): NumberedPolynomial = - with(other.coefficients) { - if (isEmpty()) NumberedPolynomialAsIs(mapOf(emptyList() to this@plus)) - else NumberedPolynomialAsIs( - withPutOrChanged(emptyList(), this@plus) { it -> this@plus + it } - ) - } + 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 = - with(other.coefficients) { - if (isEmpty()) NumberedPolynomialAsIs(mapOf(emptyList() to this@minus)) - else NumberedPolynomialAsIs( - toMutableMap() - .apply { - forEach { (degs, c) -> if (degs.isNotEmpty()) this[degs] = -c } - - val degs = emptyList() - - this[degs] = this@minus - getOrElse(degs) { constantZero } - } - ) - } + 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. */ @@ -183,22 +167,18 @@ public class NumberedPolynomialSpace>( * Returns sum of the constant represented as a polynomial and the polynomial. */ override operator fun NumberedPolynomial.plus(other: C): NumberedPolynomial = - with(coefficients) { - if (isEmpty()) NumberedPolynomialAsIs(mapOf(emptyList() to other)) - else NumberedPolynomialAsIs( - withPutOrChanged(emptyList(), other) { it -> it + other } - ) - } + 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 = - with(coefficients) { - if (isEmpty()) NumberedPolynomialAsIs(mapOf(emptyList() to other)) - else NumberedPolynomialAsIs( - withPutOrChanged(emptyList(), -other) { it -> it - other } - ) - } + 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. */ @@ -264,13 +244,7 @@ public class NumberedPolynomialSpace>( /** * Instance of unit polynomial (unit of the polynomial ring). */ - override val one: NumberedPolynomial by lazy { - NumberedPolynomialAsIs( - mapOf( - emptyList() to constantOne // 1 * x_1^0 * x_2^0 * ... - ) - ) - } + 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, 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 index 1d3da4c8b..ee32aa9a7 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/collectionUtils.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/collectionUtils.kt @@ -9,6 +9,40 @@ import kotlin.contracts.InvocationKind.* import kotlin.contracts.contract +// TODO: Docs +internal inline fun Map.computeOn(key: K, compute: (V?) -> R): R { + contract { + callsInPlace(compute, EXACTLY_ONCE) + } + return compute(get(key)) +} + +// TODO: Docs +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)) +} + +// TODO: Docs +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) +} + +// TODO: Docs +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. @@ -21,7 +55,7 @@ internal inline fun MutableMap.applyToKey(key: K, transform: (cu contract { callsInPlace(transform, EXACTLY_ONCE) } - return transform(get(key)).also { this[key] = it } + return computeOn(key, transform).also { this[key] = it } } /** @@ -39,8 +73,7 @@ internal inline fun MutableMap.putOrChange(key: K, valueOnPut: () - callsInPlace(valueOnPut, AT_MOST_ONCE) callsInPlace(transformOnChange, AT_MOST_ONCE) } - @Suppress("UNCHECKED_CAST") - return (if (key !in this) valueOnPut() else transformOnChange(get(key) as V)).also { this[key] = it } + return computeOnOrElse(key, valueOnPut, transformOnChange).also { this[key] = it } } /** -- 2.34.1 From 3a91cb2579862e7ef9d617a46d6c8b44c8e61438 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sat, 16 Jul 2022 18:46:40 +0300 Subject: [PATCH 145/275] Draft another DSL for labeled polynomials. Add variance. --- .../LabeledPolynomial.kt | 2 +- .../ListPolynomial.kt | 4 +- .../NumberedPolynomial.kt | 2 +- .../Polynomial.kt | 2 +- .../RationalFunction.kt | 6 +- .../labeledConstructors.kt | 255 ++++++++++++++++++ 6 files changed, 263 insertions(+), 8 deletions(-) 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 index 7df51930e..e2320114b 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/LabeledPolynomial.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/LabeledPolynomial.kt @@ -75,7 +75,7 @@ internal constructor( * @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 class LabeledPolynomialSpace>( public override val ring: A, ) : MultivariatePolynomialSpace>, PolynomialSpaceOverRing, A> { /** 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 index 17c42ac8c..d0e58c0d6 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/ListPolynomial.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/ListPolynomial.kt @@ -60,7 +60,7 @@ public data class ListPolynomial( * @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 open class ListPolynomialSpace>( public override val ring: A, ) : PolynomialSpaceOverRing, A> { /** @@ -366,7 +366,7 @@ public open class ListPolynomialSpace>( * @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( +public class ScalableListPolynomialSpace( ring: A, ) : ListPolynomialSpace(ring), ScaleOperations> where A : Ring, A : ScaleOperations { override fun scale(a: ListPolynomial, value: Double): ListPolynomial = 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 index 037419cfc..d2fc5ffa1 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/NumberedPolynomial.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/NumberedPolynomial.kt @@ -59,7 +59,7 @@ internal constructor( * @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 class NumberedPolynomialSpace>( public override val ring: A, ) : PolynomialSpaceOverRing, A> { /** 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 index 61ea5a342..66308a7bc 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/Polynomial.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/Polynomial.kt @@ -252,7 +252,7 @@ public interface PolynomialSpace> : Ring

{ * @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, A: Ring> : PolynomialSpace { +public interface PolynomialSpaceOverRing, out A: Ring> : PolynomialSpace { /** * Underlying ring of constants. Its operations on constants are inherited by local operations on constants. 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 index f664ae9db..da91c8d61 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/RationalFunction.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/RationalFunction.kt @@ -464,7 +464,7 @@ public interface RationalFunctionSpaceOverRing< C, P: Polynomial, R: RationalFunction, - A: Ring + out A: Ring > : RationalFunctionSpace { /** @@ -566,7 +566,7 @@ public interface RationalFunctionSpaceOverPolynomialSpace< C, P: Polynomial, R: RationalFunction, - AP: PolynomialSpace, + out AP: PolynomialSpace, > : RationalFunctionSpace { /** @@ -1341,7 +1341,7 @@ public interface MultivariateRationalFunctionSpaceOverMultivariatePolynomialSpac V, P: Polynomial, R: RationalFunction, - AP: MultivariatePolynomialSpace, + out AP: MultivariatePolynomialSpace, > : RationalFunctionSpaceOverPolynomialSpace, MultivariateRationalFunctionSpace { /** * Returns sum of the variable represented as a monic monomial and the integer represented as a constant polynomial. 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 index 43048089e..d74c0e1fb 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/labeledConstructors.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/labeledConstructors.kt @@ -416,6 +416,261 @@ public inline fun > LabeledPolynomialSpace.LabeledPolynomial @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.submit() = submit(emptyMap(), { this@submit }) + + 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 { + submit() + 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.submit() + 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.submit() + 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 /** -- 2.34.1 From 58d7015782bc24c12e11ff2c84d0fe2c631a3c59 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sat, 16 Jul 2022 20:15:30 +0300 Subject: [PATCH 146/275] Remove utils modules. Revive suddenly lost tests. --- kmath-functions/build.gradle.kts | 5 - .../kmath/functions/testUtils/IntModulo.kt | 38 +- .../functions/testUtils/IntModuloUtils.kt | 8 +- .../kmath/functions/testUtils/Rational.kt | 54 +- .../kmath/functions/testUtils/misc.kt | 0 kmath-polynomial/build.gradle.kts | 6 - .../kmath/functions/AlgebraicStubTest.kt | 589 +++++++++++ .../kmath/functions/ListPolynomialTest.kt | 544 ++++++++++ .../kmath/functions/ListPolynomialUtilTest.kt | 982 ++++++++++++++++++ .../kmath/functions/testUtils/BufferUtils.kt | 2 +- .../kmath/functions/testUtils/IntModulo.kt | 38 +- .../functions/testUtils/IntModuloUtils.kt | 9 +- .../kmath/functions/testUtils/NTMisc.kt | 0 .../kmath/functions/testUtils/Rational.kt | 54 +- .../kmath/functions/testUtils/assertion.kt | 12 +- .../kmath/functions/testUtils/misc.kt | 14 +- settings.gradle.kts | 2 - test-utils-functions/build.gradle.kts | 14 - .../kmath/functions/testUtils/assertion.kt | 22 - test-utils-polynomial/build.gradle.kts | 14 - 20 files changed, 2229 insertions(+), 178 deletions(-) rename {test-utils-functions/src/commonMain => kmath-functions/src/commonTest}/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt (80%) rename {test-utils-functions/src/commonMain => kmath-functions/src/commonTest}/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt (54%) rename {test-utils-polynomial/src/commonMain => kmath-functions/src/commonTest}/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt (78%) rename {test-utils-functions/src/commonMain => kmath-functions/src/commonTest}/kotlin/space/kscience/kmath/functions/testUtils/misc.kt (100%) create mode 100644 kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt create mode 100644 kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt create mode 100644 kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt rename {test-utils-polynomial/src/commonMain => kmath-polynomial/src/commonTest}/kotlin/space/kscience/kmath/functions/testUtils/BufferUtils.kt (80%) rename {test-utils-polynomial/src/commonMain => kmath-polynomial/src/commonTest}/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt (79%) rename {test-utils-polynomial/src/commonMain => kmath-polynomial/src/commonTest}/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt (53%) rename {test-utils-polynomial/src/commonMain => kmath-polynomial/src/commonTest}/kotlin/space/kscience/kmath/functions/testUtils/NTMisc.kt (100%) rename {test-utils-functions/src/commonMain => kmath-polynomial/src/commonTest}/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt (78%) rename {test-utils-polynomial/src/commonMain => kmath-polynomial/src/commonTest}/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt (92%) rename {test-utils-polynomial/src/commonMain => kmath-polynomial/src/commonTest}/kotlin/space/kscience/kmath/functions/testUtils/misc.kt (58%) delete mode 100644 test-utils-functions/build.gradle.kts delete mode 100644 test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt delete mode 100644 test-utils-polynomial/build.gradle.kts diff --git a/kmath-functions/build.gradle.kts b/kmath-functions/build.gradle.kts index 149a8f277..eec17e82b 100644 --- a/kmath-functions/build.gradle.kts +++ b/kmath-functions/build.gradle.kts @@ -12,11 +12,6 @@ kotlin.sourceSets { api(project(":kmath-core")) } } - commonTest { - dependencies { - api(projects.testUtilsFunctions) - } - } } dependencies { diff --git a/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt similarity index 80% rename from test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt rename to kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt index 21095d858..ef601c941 100644 --- a/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt @@ -11,9 +11,9 @@ import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.ScaleOperations -public class IntModulo { - public val residue: Int - public val modulus: Int +class IntModulo { + val residue: Int + val modulus: Int @PublishedApi internal constructor(residue: Int, modulus: Int, toCheckInput: Boolean = true) { @@ -27,16 +27,16 @@ public class IntModulo { } } - public constructor(residue: Int, modulus: Int) : this(residue, modulus, true) + constructor(residue: Int, modulus: Int) : this(residue, modulus, true) - public operator fun unaryPlus(): IntModulo = this - public operator fun unaryMinus(): IntModulo = + operator fun unaryPlus(): IntModulo = this + operator fun unaryMinus(): IntModulo = IntModulo( if (residue == 0) 0 else modulus - residue, modulus, toCheckInput = false ) - public operator fun plus(other: IntModulo): IntModulo { + operator fun plus(other: IntModulo): IntModulo { require(modulus == other.modulus) { "can not add two residue different modulo" } return IntModulo( (residue + other.residue) % modulus, @@ -44,13 +44,13 @@ public class IntModulo { toCheckInput = false ) } - public operator fun plus(other: Int): IntModulo = + operator fun plus(other: Int): IntModulo = IntModulo( (residue + other) % modulus, modulus, toCheckInput = false ) - public operator fun minus(other: IntModulo): IntModulo { + operator fun minus(other: IntModulo): IntModulo { require(modulus == other.modulus) { "can not subtract two residue different modulo" } return IntModulo( (residue - other.residue) % modulus, @@ -58,13 +58,13 @@ public class IntModulo { toCheckInput = false ) } - public operator fun minus(other: Int): IntModulo = + operator fun minus(other: Int): IntModulo = IntModulo( (residue - other) % modulus, modulus, toCheckInput = false ) - public operator fun times(other: IntModulo): IntModulo { + operator fun times(other: IntModulo): IntModulo { require(modulus == other.modulus) { "can not multiply two residue different modulo" } return IntModulo( (residue * other.residue) % modulus, @@ -72,13 +72,13 @@ public class IntModulo { toCheckInput = false ) } - public operator fun times(other: Int): IntModulo = + operator fun times(other: Int): IntModulo = IntModulo( (residue * other) % modulus, modulus, toCheckInput = false ) - public operator fun div(other: IntModulo): IntModulo { + 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" } @@ -88,7 +88,7 @@ public class IntModulo { toCheckInput = false ) } - public operator fun div(other: Int): IntModulo { + 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( @@ -109,11 +109,11 @@ public class IntModulo { } @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE") -public class IntModuloRing : Ring, ScaleOperations { +class IntModuloRing : Ring, ScaleOperations { - public val modulus: Int + val modulus: Int - public constructor(modulus: Int) { + constructor(modulus: Int) { require(modulus != 0) { "modulus can not be zero" } this.modulus = if (modulus < 0) -modulus else modulus } @@ -121,7 +121,7 @@ public class IntModuloRing : Ring, ScaleOperations { override inline val zero: IntModulo get() = IntModulo(0, modulus, toCheckInput = false) override inline val one: IntModulo get() = IntModulo(1, modulus, toCheckInput = false) - public fun number(arg: Int): IntModulo = IntModulo(arg, 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 @@ -130,7 +130,7 @@ public class IntModuloRing : Ring, ScaleOperations { 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 - public inline fun IntModulo.div(arg: IntModulo): IntModulo = this / arg + inline fun IntModulo.div(arg: IntModulo): IntModulo = this / arg override fun scale(a: IntModulo, value: Double): IntModulo = a * value.toInt() } \ No newline at end of file diff --git a/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt similarity index 54% rename from test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt rename to kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt index e534c243e..730a455bf 100644 --- a/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt @@ -9,10 +9,10 @@ import space.kscience.kmath.functions.Polynomial import space.kscience.kmath.functions.PolynomialSpace -public fun PolynomialSpace.Polynomial(vararg coefs: Int): Polynomial = +fun PolynomialSpace.Polynomial(vararg coefs: Int): Polynomial = Polynomial(coefs.map { IntModulo(it, ring.modulus) }) -public fun IntModuloRing.Polynomial(vararg coefs: Int): Polynomial = +fun IntModuloRing.Polynomial(vararg coefs: Int): Polynomial = Polynomial(coefs.map { IntModulo(it, modulus) }) -public fun IntModuloRing.m(arg: Int): IntModulo = IntModulo(arg, modulus) -public fun PolynomialSpace.m(arg: Int): IntModulo = IntModulo(arg, ring.modulus) \ No newline at end of file +fun IntModuloRing.m(arg: Int): IntModulo = IntModulo(arg, modulus) +fun PolynomialSpace.m(arg: Int): IntModulo = IntModulo(arg, ring.modulus) \ No newline at end of file diff --git a/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt similarity index 78% rename from test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt rename to kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt index 27b0eb21e..19cb77df5 100644 --- a/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt @@ -12,14 +12,14 @@ import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.NumbersAddOps @Suppress("NAME_SHADOWING") -public class Rational { - public companion object { - public val ZERO: Rational = Rational(0L) - public val ONE: Rational = Rational(1L) +class Rational { + companion object { + val ZERO: Rational = Rational(0L) + val ONE: Rational = Rational(1L) } - public val numerator: Long - public val denominator: Long + val numerator: Long + val denominator: Long internal constructor(numerator: Long, denominator: Long, toCheckInput: Boolean = true) { if (toCheckInput) { @@ -35,16 +35,16 @@ public class Rational { } } - public constructor(numerator: Int, denominator: Int) : this(numerator.toLong(), denominator.toLong(), true) - public constructor(numerator: Int, denominator: Long) : this(numerator.toLong(), denominator, true) - public constructor(numerator: Long, denominator: Int) : this(numerator, denominator.toLong(), true) - public constructor(numerator: Long, denominator: Long) : this(numerator, denominator, true) - public constructor(numerator: Int) : this(numerator.toLong(), 1L, false) - public constructor(numerator: Long) : this(numerator, 1L, false) + 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) - public operator fun unaryPlus(): Rational = this - public operator fun unaryMinus(): Rational = Rational(-this.numerator, this.denominator) - public operator fun plus(other: Rational): Rational { + 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 @@ -56,19 +56,19 @@ public class Rational { toCheckInput = false ) } - public operator fun plus(other: Int): Rational = + operator fun plus(other: Int): Rational = Rational( numerator + denominator * other.toLong(), denominator, toCheckInput = false ) - public operator fun plus(other: Long): Rational = + operator fun plus(other: Long): Rational = Rational( numerator + denominator * other, denominator, toCheckInput = false ) - public operator fun minus(other: Rational): Rational { + operator fun minus(other: Rational): Rational { val denominatorsGcd = gcd(denominator, other.denominator) val dividedThisDenominator = denominator / denominatorsGcd val dividedOtherDenominator = other.denominator / denominatorsGcd @@ -80,19 +80,19 @@ public class Rational { toCheckInput = false ) } - public operator fun minus(other: Int): Rational = + operator fun minus(other: Int): Rational = Rational( numerator - denominator * other.toLong(), denominator, toCheckInput = false ) - public operator fun minus(other: Long): Rational = + operator fun minus(other: Long): Rational = Rational( numerator - denominator * other, denominator, toCheckInput = false ) - public operator fun times(other: Rational): Rational { + operator fun times(other: Rational): Rational { val thisDenominatorAndOtherNumeratorGcd = gcd(denominator, other.numerator) val otherDenominatorAndThisNumeratorGcd = gcd(other.denominator, numerator) return Rational( @@ -101,7 +101,7 @@ public class Rational { toCheckInput = false ) } - public operator fun times(other: Int): Rational { + operator fun times(other: Int): Rational { val other = other.toLong() val denominatorAndOtherGcd = gcd(denominator, other) return Rational( @@ -110,7 +110,7 @@ public class Rational { toCheckInput = false ) } - public operator fun times(other: Long): Rational { + operator fun times(other: Long): Rational { val denominatorAndOtherGcd = gcd(denominator, other) return Rational( numerator * (other / denominatorAndOtherGcd), @@ -118,7 +118,7 @@ public class Rational { toCheckInput = false ) } - public operator fun div(other: Rational): Rational { + operator fun div(other: Rational): Rational { val denominatorsGcd = gcd(denominator, other.denominator) val numeratorsGcd = gcd(numerator, other.numerator) return Rational( @@ -126,7 +126,7 @@ public class Rational { (denominator / denominatorsGcd) * (other.numerator / numeratorsGcd) ) } - public operator fun div(other: Int): Rational { + operator fun div(other: Int): Rational { val other = other.toLong() val numeratorAndOtherGcd = gcd(numerator, other) return Rational( @@ -135,7 +135,7 @@ public class Rational { toCheckInput = false ) } - public operator fun div(other: Long): Rational { + operator fun div(other: Long): Rational { val numeratorAndOtherGcd = gcd(numerator, other) return Rational( numerator / numeratorAndOtherGcd, @@ -158,7 +158,7 @@ public class Rational { @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE") @OptIn(UnstableKMathAPI::class) -public object RationalField : Field, NumbersAddOps { +object RationalField : Field, NumbersAddOps { override inline val zero: Rational get() = Rational.ZERO override inline val one: Rational get() = Rational.ONE diff --git a/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/misc.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/misc.kt similarity index 100% rename from test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/misc.kt rename to kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/misc.kt diff --git a/kmath-polynomial/build.gradle.kts b/kmath-polynomial/build.gradle.kts index b0f4a095c..85b87fb34 100644 --- a/kmath-polynomial/build.gradle.kts +++ b/kmath-polynomial/build.gradle.kts @@ -12,12 +12,6 @@ kotlin.sourceSets { api(projects.kmathCore) } } - commonTest { - dependencies { - api(projects.testUtilsPolynomial) - api(kotlin("test")) - } - } } dependencies { diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt new file mode 100644 index 000000000..487cd9ee1 --- /dev/null +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt @@ -0,0 +1,589 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.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/ListPolynomialTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt new file mode 100644 index 000000000..e7d8dfd8c --- /dev/null +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt @@ -0,0 +1,544 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +@file:Suppress("LocalVariableName") + +package space.kscience.kmath.functions + +import space.kscience.kmath.functions.testUtils.IntModuloRing +import space.kscience.kmath.functions.testUtils.ListPolynomial +import space.kscience.kmath.functions.testUtils.Rational +import space.kscience.kmath.functions.testUtils.RationalField +import kotlin.test.* + + +class ListPolynomialTest { + @Test + fun test_Polynomial_Int_plus() { + RationalField.listPolynomialSpace { + assertEquals( + ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)), + ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + -3, + "test 1" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + 2, + "test 2" + ) + assertEquals( + ListPolynomial(Rational(0)), + ListPolynomial(Rational(-2)) + 2, + "test 3" + ) + val polynomial_4 = ListPolynomial() + assertSame( + polynomial_4, + polynomial_4 + 0, + "test 4" + ) + val polynomial_5 = ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)) + assertSame( + polynomial_5, + polynomial_5 + 0, + "test 5" + ) + assertEquals( + ListPolynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), + ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + 1, + "test 6" + ) + assertEquals( + ListPolynomial(Rational(-1)), + ListPolynomial(Rational(-2)) + 1, + "test 7" + ) + assertEquals( + ListPolynomial(Rational(2)), + ListPolynomial() + 2, + "test 8" + ) + } + } + @Test + fun test_Polynomial_Int_minus() { + RationalField.listPolynomialSpace { + assertEquals( + ListPolynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), + ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - -3, + "test 1" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + ListPolynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - 2, + "test 2" + ) + assertEquals( + ListPolynomial(Rational(0)), + ListPolynomial(Rational(2)) - 2, + "test 3" + ) + val polynomial_4 = ListPolynomial() + assertSame( + polynomial_4, + polynomial_4 - 0, + "test 4" + ) + val polynomial_5 = ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)) + assertEquals( + polynomial_5, + polynomial_5 - 0, + "test 5" + ) + assertEquals( + ListPolynomial(Rational(1), Rational(0), Rational(0), Rational(0)), + ListPolynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - 1, + "test 6" + ) + assertEquals( + ListPolynomial(Rational(1)), + ListPolynomial(Rational(2)) - 1, + "test 7" + ) + assertEquals( + ListPolynomial(Rational(-2)), + ListPolynomial() - 2, + "test 8" + ) + } + } + @Test + fun test_Polynomial_Int_times() { + IntModuloRing(35).listPolynomialSpace { + assertEquals( + ListPolynomial(34, 2, 1, 20, 2), + ListPolynomial(22, 26, 13, 15, 26) * 27, + "test 1" + ) + assertEquals( + ListPolynomial(0, 0, 0, 0, 0), + ListPolynomial(7, 0, 49, 21, 14) * 15, + "test 2" + ) + val polynomial = ListPolynomial(22, 26, 13, 15, 26) + assertSame( + zero, + polynomial * 0, + "test 3" + ) + assertSame( + polynomial, + polynomial * 1, + "test 4" + ) + } + } + @Test + fun test_Int_Polynomial_plus() { + RationalField.listPolynomialSpace { + assertEquals( + ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)), + -3 + ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)), + "test 1" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + 2 + ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 2" + ) + assertEquals( + ListPolynomial(Rational(0)), + 2 + ListPolynomial(Rational(-2)), + "test 3" + ) + val polynomial_4 = ListPolynomial() + assertSame( + polynomial_4, + 0 + polynomial_4, + "test 4" + ) + val polynomial_5 = ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)) + assertSame( + polynomial_5, + 0 + polynomial_5, + "test 5" + ) + assertEquals( + ListPolynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), + 1 + ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 6" + ) + assertEquals( + ListPolynomial(Rational(-1)), + 1 + ListPolynomial(Rational(-2)), + "test 7" + ) + assertEquals( + ListPolynomial(Rational(2)), + 2 + ListPolynomial(), + "test 8" + ) + } + } + @Test + fun test_Int_Polynomial_minus() { + RationalField.listPolynomialSpace { + assertEquals( + ListPolynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), + 3 - ListPolynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7)), + "test 1" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + -2 - ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 2" + ) + assertEquals( + ListPolynomial(Rational(0)), + -2 - ListPolynomial(Rational(-2)), + "test 3" + ) + assertEquals( + ListPolynomial(Rational(-32, 9), Rational(-8, -9), Rational(8, 7)), + 0 - ListPolynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), + "test 4" + ) + assertEquals( + ListPolynomial(), + 0 - ListPolynomial(), + "test 5" + ) + assertEquals( + ListPolynomial(Rational(1), Rational(0), Rational(0), Rational(0)), + -1 - ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 6" + ) + assertEquals( + ListPolynomial(Rational(1)), + -1 - ListPolynomial(Rational(-2)), + "test 7" + ) + assertEquals( + ListPolynomial(Rational(-2)), + -2 - ListPolynomial(), + "test 8" + ) + } + } + @Test + fun test_Int_Polynomial_times() { + IntModuloRing(35).listPolynomialSpace { + assertEquals( + ListPolynomial(34, 2, 1, 20, 2), + 27 * ListPolynomial(22, 26, 13, 15, 26), + "test 1" + ) + assertEquals( + ListPolynomial(0, 0, 0, 0, 0), + 15 * ListPolynomial(7, 0, 49, 21, 14), + "test 2" + ) + val polynomial = ListPolynomial(22, 26, 13, 15, 26) + assertSame( + zero, + 0 * polynomial, + "test 3" + ) + assertSame( + polynomial, + 1 * polynomial, + "test 4" + ) + } + } + @Test + fun test_Polynomial_Constant_plus() { + RationalField.listPolynomialSpace { + assertEquals( + ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)), + ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + Rational(-3), + "test 1" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + Rational(2), + "test 2" + ) + assertEquals( + ListPolynomial(Rational(0)), + ListPolynomial(Rational(-2)) + Rational(2), + "test 3" + ) + assertEquals( + ListPolynomial(Rational(0)), + ListPolynomial() + Rational(0), + "test 4" + ) + assertEquals( + ListPolynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), + ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + Rational(1), + "test 5" + ) + assertEquals( + ListPolynomial(Rational(-1)), + ListPolynomial(Rational(-2)) + Rational(1), + "test 6" + ) + assertEquals( + ListPolynomial(Rational(2)), + ListPolynomial() + Rational(2), + "test 7" + ) + } + } + @Test + fun test_Polynomial_Constant_minus() { + RationalField.listPolynomialSpace { + assertEquals( + ListPolynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), + ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - Rational(-3), + "test 1" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + ListPolynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - Rational(2), + "test 2" + ) + assertEquals( + ListPolynomial(Rational(0)), + ListPolynomial(Rational(2)) - Rational(2), + "test 3" + ) + assertEquals( + ListPolynomial(Rational(0)), + ListPolynomial() - Rational(0), + "test 4" + ) + assertEquals( + ListPolynomial(Rational(1), Rational(0), Rational(0), Rational(0)), + ListPolynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - Rational(1), + "test 5" + ) + assertEquals( + ListPolynomial(Rational(1)), + ListPolynomial(Rational(2)) - Rational(1), + "test 6" + ) + assertEquals( + ListPolynomial(Rational(-2)), + ListPolynomial() - Rational(2), + "test 7" + ) + } + } + @Test + fun test_Polynomial_Constant_times() { + IntModuloRing(35).listPolynomialSpace { + assertEquals( + ListPolynomial(34, 2, 1, 20, 2), + ListPolynomial(22, 26, 13, 15, 26) * 27.asConstant(), + "test 1" + ) + assertEquals( + ListPolynomial(0, 0, 0, 0, 0), + ListPolynomial(7, 0, 49, 21, 14) * 15.asConstant(), + "test 2" + ) + } + } + @Test + fun test_Constant_Polynomial_plus() { + RationalField.listPolynomialSpace { + assertEquals( + ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)), + Rational(-3) + ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)), + "test 1" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + Rational(2) + ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 2" + ) + assertEquals( + ListPolynomial(Rational(0)), + Rational(2) + ListPolynomial(Rational(-2)), + "test 3" + ) + assertEquals( + ListPolynomial(Rational(0)), + Rational(0) + ListPolynomial(), + "test 4" + ) + assertEquals( + ListPolynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), + Rational(1) + ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 5" + ) + assertEquals( + ListPolynomial(Rational(-1)), + Rational(1) + ListPolynomial(Rational(-2)), + "test 6" + ) + assertEquals( + ListPolynomial(Rational(2)), + Rational(2) + ListPolynomial(), + "test 7" + ) + } + } + @Test + fun test_Constant_Polynomial_minus() { + RationalField.listPolynomialSpace { + assertEquals( + ListPolynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)), + Rational(3) - ListPolynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7)), + "test 1" + ) + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0)), + Rational(-2) - ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 2" + ) + assertEquals( + ListPolynomial(Rational(0)), + Rational(-2) - ListPolynomial(Rational(-2)), + "test 3" + ) + assertEquals( + ListPolynomial(Rational(0)), + Rational(0) - ListPolynomial(), + "test 4" + ) + assertEquals( + ListPolynomial(Rational(1), Rational(0), Rational(0), Rational(0)), + Rational(-1) - ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), + "test 5" + ) + assertEquals( + ListPolynomial(Rational(1)), + Rational(-1) - ListPolynomial(Rational(-2)), + "test 6" + ) + assertEquals( + ListPolynomial(Rational(-2)), + Rational(-2) - ListPolynomial(), + "test 7" + ) + } + } + @Test + fun test_Constant_Polynomial_times() { + IntModuloRing(35).listPolynomialSpace { + assertEquals( + ListPolynomial(34, 2, 1, 20, 2), + 27 * ListPolynomial(22, 26, 13, 15, 26), + "test 1" + ) + assertEquals( + ListPolynomial(0, 0, 0, 0, 0), + 15 * ListPolynomial(7, 0, 49, 21, 14), + "test 2" + ) + } + } + @Test + fun test_Polynomial_unaryMinus() { + RationalField.listPolynomialSpace { + assertEquals( + ListPolynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7)), + -ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)), + "test 1" + ) + assertEquals( + ListPolynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7), Rational(0), Rational(0)), + -ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7), Rational(0), Rational(0)), + "test 2" + ) + } + } + @Test + fun test_Polynomial_Polynomial_plus() { + RationalField.listPolynomialSpace { + // (5/9 - 8/9 x - 8/7 x^2) + (-5/7 + 5/1 x + 5/8 x^2) ?= -10/63 + 37/9 x - 29/56 x^2 + assertEquals( + ListPolynomial(Rational(-10, 63), Rational(37, 9), Rational(-29, 56)), + ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + + ListPolynomial(Rational(-5, 7), Rational(5, 1), Rational(5, 8)), + "test 1" + ) + // (-2/9 - 8/3 x) + (0 + 9/4 x + 2/4 x^2) ?= -2/9 - 5/12 x + 2/4 x^2 + assertEquals( + ListPolynomial(Rational(-2, 9), Rational(-5, 12), Rational(2, 4)), + ListPolynomial(Rational(-2, 9), Rational(-8, 3)) + + ListPolynomial(Rational(0), Rational(9, 4), Rational(2, 4)), + "test 2" + ) + // (-4/7 - 2/6 x + 0 x^2 + 0 x^3) + (-6/3 - 7/2 x + 2/3 x^2) ?= -18/7 - 23/6 x + 2/3 x^2 + assertEquals( + ListPolynomial(Rational(-18, 7), Rational(-23, 6), Rational(2, 3), Rational(0)), + ListPolynomial(Rational(-4, 7), Rational(-2, 6), Rational(0), Rational(0)) + + ListPolynomial(Rational(-6, 3), Rational(-7, 2), Rational(2, 3)), + "test 3" + ) + // (-2/4 - 6/9 x - 4/9 x^2) + (2/4 + 6/9 x + 4/9 x^2) ?= 0 + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(0)), + ListPolynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)) + + ListPolynomial(Rational(2, 4), Rational(6, 9), Rational(4, 9)), + "test 4" + ) + } + } + @Test + fun test_Polynomial_Polynomial_minus() { + RationalField.listPolynomialSpace { + // (5/9 - 8/9 x - 8/7 x^2) - (-5/7 + 5/1 x + 5/8 x^2) ?= 80/63 - 53/9 x - 99/56 x^2 + assertEquals( + ListPolynomial(Rational(80, 63), Rational(-53, 9), Rational(-99, 56)), + ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - + ListPolynomial(Rational(-5, 7), Rational(5, 1), Rational(5, 8)), + "test 1" + ) + // (-2/9 - 8/3 x) - (0 + 9/4 x + 2/4 x^2) ?= -2/9 - 59/12 x - 2/4 x^2 + assertEquals( + ListPolynomial(Rational(-2, 9), Rational(-59, 12), Rational(-2, 4)), + ListPolynomial(Rational(-2, 9), Rational(-8, 3)) - + ListPolynomial(Rational(0), Rational(9, 4), Rational(2, 4)), + "test 2" + ) + // (-4/7 - 2/6 x + 0 x^2 + 0 x^3) - (-6/3 - 7/2 x + 2/3 x^2) ?= 10/7 + 19/6 x - 2/3 x^2 + assertEquals( + ListPolynomial(Rational(10, 7), Rational(19, 6), Rational(-2, 3), Rational(0)), + ListPolynomial(Rational(-4, 7), Rational(-2, 6), Rational(0), Rational(0)) - + ListPolynomial(Rational(-6, 3), Rational(-7, 2), Rational(2, 3)), + "test 3" + ) + // (-2/4 - 6/9 x - 4/9 x^2) - (-2/4 - 6/9 x - 4/9 x^2) ?= 0 + assertEquals( + ListPolynomial(Rational(0), Rational(0), Rational(0)), + ListPolynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)) - + ListPolynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)), + "test 4" + ) + } + } + @Test + fun test_Polynomial_Polynomial_times() { + IntModuloRing(35).listPolynomialSpace { + // (1 + x + x^2) * (1 - x + x^2) ?= 1 + x^2 + x^4 + assertEquals( + ListPolynomial(1, 0, 1, 0, 1), + ListPolynomial(1, -1, 1) * ListPolynomial(1, 1, 1), + "test 1" + ) + // Spoiler: 5 * 7 = 0 + assertEquals( + ListPolynomial(0, 0, 0, 0, 0), + ListPolynomial(5, -25, 10) * ListPolynomial(21, 14, -7), + "test 2" + ) + } + } +} \ No newline at end of file diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt new file mode 100644 index 000000000..339643d02 --- /dev/null +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt @@ -0,0 +1,982 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.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/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/BufferUtils.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/BufferUtils.kt similarity index 80% rename from test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/BufferUtils.kt rename to kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/BufferUtils.kt index afd26dd36..3297733b1 100644 --- a/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/BufferUtils.kt +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/BufferUtils.kt @@ -9,4 +9,4 @@ import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asBuffer -public fun bufferOf(vararg elements: T): Buffer = elements.asBuffer() \ No newline at end of file +fun bufferOf(vararg elements: T): Buffer = elements.asBuffer() \ No newline at end of file diff --git a/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt similarity index 79% rename from test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt rename to kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt index 933c4dc4c..5bac4cd73 100644 --- a/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt @@ -10,9 +10,9 @@ package space.kscience.kmath.functions.testUtils import space.kscience.kmath.operations.Ring -public class IntModulo { - public val residue: Int - public val modulus: Int +class IntModulo { + val residue: Int + val modulus: Int @PublishedApi internal constructor(residue: Int, modulus: Int, toCheckInput: Boolean = true) { @@ -26,16 +26,16 @@ public class IntModulo { } } - public constructor(residue: Int, modulus: Int) : this(residue, modulus, true) + constructor(residue: Int, modulus: Int) : this(residue, modulus, true) - public operator fun unaryPlus(): IntModulo = this - public operator fun unaryMinus(): IntModulo = + operator fun unaryPlus(): IntModulo = this + operator fun unaryMinus(): IntModulo = IntModulo( if (residue == 0) 0 else modulus - residue, modulus, toCheckInput = false ) - public operator fun plus(other: IntModulo): IntModulo { + operator fun plus(other: IntModulo): IntModulo { require(modulus == other.modulus) { "can not add two residue different modulo" } return IntModulo( (residue + other.residue) % modulus, @@ -43,13 +43,13 @@ public class IntModulo { toCheckInput = false ) } - public operator fun plus(other: Int): IntModulo = + operator fun plus(other: Int): IntModulo = IntModulo( (residue + other) % modulus, modulus, toCheckInput = false ) - public operator fun minus(other: IntModulo): IntModulo { + operator fun minus(other: IntModulo): IntModulo { require(modulus == other.modulus) { "can not subtract two residue different modulo" } return IntModulo( (residue - other.residue) % modulus, @@ -57,13 +57,13 @@ public class IntModulo { toCheckInput = false ) } - public operator fun minus(other: Int): IntModulo = + operator fun minus(other: Int): IntModulo = IntModulo( (residue - other) % modulus, modulus, toCheckInput = false ) - public operator fun times(other: IntModulo): IntModulo { + operator fun times(other: IntModulo): IntModulo { require(modulus == other.modulus) { "can not multiply two residue different modulo" } return IntModulo( (residue * other.residue) % modulus, @@ -71,13 +71,13 @@ public class IntModulo { toCheckInput = false ) } - public operator fun times(other: Int): IntModulo = + operator fun times(other: Int): IntModulo = IntModulo( (residue * other) % modulus, modulus, toCheckInput = false ) - public operator fun div(other: IntModulo): IntModulo { + 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" } @@ -87,7 +87,7 @@ public class IntModulo { toCheckInput = false ) } - public operator fun div(other: Int): IntModulo { + 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( @@ -108,11 +108,11 @@ public class IntModulo { } @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE") -public class IntModuloRing : Ring { +class IntModuloRing : Ring { - public val modulus: Int + val modulus: Int - public constructor(modulus: Int) { + constructor(modulus: Int) { require(modulus != 0) { "modulus can not be zero" } this.modulus = if (modulus < 0) -modulus else modulus } @@ -120,7 +120,7 @@ public class IntModuloRing : Ring { override inline val zero: IntModulo get() = IntModulo(0, modulus, toCheckInput = false) override inline val one: IntModulo get() = IntModulo(1, modulus, toCheckInput = false) - public fun number(arg: Int): IntModulo = IntModulo(arg, 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 @@ -129,5 +129,5 @@ public class IntModuloRing : Ring { 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 - public inline fun IntModulo.div(arg: IntModulo): IntModulo = this / arg + inline fun IntModulo.div(arg: IntModulo): IntModulo = this / arg } \ No newline at end of file diff --git a/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt similarity index 53% rename from test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt rename to kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt index 32ca1c3aa..33fd03aa0 100644 --- a/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt @@ -6,15 +6,14 @@ package space.kscience.kmath.functions.testUtils import space.kscience.kmath.functions.ListPolynomial -import space.kscience.kmath.functions.Polynomial import space.kscience.kmath.functions.ListPolynomialSpace import space.kscience.kmath.functions.PolynomialSpaceOverRing -public fun ListPolynomialSpace.ListPolynomial(vararg coefs: Int): ListPolynomial = +fun ListPolynomialSpace.ListPolynomial(vararg coefs: Int): ListPolynomial = ListPolynomial(coefs.map { IntModulo(it, ring.modulus) }) -public fun IntModuloRing.ListPolynomial(vararg coefs: Int): ListPolynomial = +fun IntModuloRing.ListPolynomial(vararg coefs: Int): ListPolynomial = ListPolynomial(coefs.map { IntModulo(it, modulus) }) -public fun IntModuloRing.m(arg: Int): IntModulo = IntModulo(arg, modulus) -public fun PolynomialSpaceOverRing.m(arg: Int): IntModulo = IntModulo(arg, ring.modulus) \ No newline at end of file +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/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/NTMisc.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/NTMisc.kt similarity index 100% rename from test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/NTMisc.kt rename to kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/NTMisc.kt diff --git a/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt similarity index 78% rename from test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt rename to kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt index 27b0eb21e..19cb77df5 100644 --- a/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt @@ -12,14 +12,14 @@ import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.NumbersAddOps @Suppress("NAME_SHADOWING") -public class Rational { - public companion object { - public val ZERO: Rational = Rational(0L) - public val ONE: Rational = Rational(1L) +class Rational { + companion object { + val ZERO: Rational = Rational(0L) + val ONE: Rational = Rational(1L) } - public val numerator: Long - public val denominator: Long + val numerator: Long + val denominator: Long internal constructor(numerator: Long, denominator: Long, toCheckInput: Boolean = true) { if (toCheckInput) { @@ -35,16 +35,16 @@ public class Rational { } } - public constructor(numerator: Int, denominator: Int) : this(numerator.toLong(), denominator.toLong(), true) - public constructor(numerator: Int, denominator: Long) : this(numerator.toLong(), denominator, true) - public constructor(numerator: Long, denominator: Int) : this(numerator, denominator.toLong(), true) - public constructor(numerator: Long, denominator: Long) : this(numerator, denominator, true) - public constructor(numerator: Int) : this(numerator.toLong(), 1L, false) - public constructor(numerator: Long) : this(numerator, 1L, false) + 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) - public operator fun unaryPlus(): Rational = this - public operator fun unaryMinus(): Rational = Rational(-this.numerator, this.denominator) - public operator fun plus(other: Rational): Rational { + 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 @@ -56,19 +56,19 @@ public class Rational { toCheckInput = false ) } - public operator fun plus(other: Int): Rational = + operator fun plus(other: Int): Rational = Rational( numerator + denominator * other.toLong(), denominator, toCheckInput = false ) - public operator fun plus(other: Long): Rational = + operator fun plus(other: Long): Rational = Rational( numerator + denominator * other, denominator, toCheckInput = false ) - public operator fun minus(other: Rational): Rational { + operator fun minus(other: Rational): Rational { val denominatorsGcd = gcd(denominator, other.denominator) val dividedThisDenominator = denominator / denominatorsGcd val dividedOtherDenominator = other.denominator / denominatorsGcd @@ -80,19 +80,19 @@ public class Rational { toCheckInput = false ) } - public operator fun minus(other: Int): Rational = + operator fun minus(other: Int): Rational = Rational( numerator - denominator * other.toLong(), denominator, toCheckInput = false ) - public operator fun minus(other: Long): Rational = + operator fun minus(other: Long): Rational = Rational( numerator - denominator * other, denominator, toCheckInput = false ) - public operator fun times(other: Rational): Rational { + operator fun times(other: Rational): Rational { val thisDenominatorAndOtherNumeratorGcd = gcd(denominator, other.numerator) val otherDenominatorAndThisNumeratorGcd = gcd(other.denominator, numerator) return Rational( @@ -101,7 +101,7 @@ public class Rational { toCheckInput = false ) } - public operator fun times(other: Int): Rational { + operator fun times(other: Int): Rational { val other = other.toLong() val denominatorAndOtherGcd = gcd(denominator, other) return Rational( @@ -110,7 +110,7 @@ public class Rational { toCheckInput = false ) } - public operator fun times(other: Long): Rational { + operator fun times(other: Long): Rational { val denominatorAndOtherGcd = gcd(denominator, other) return Rational( numerator * (other / denominatorAndOtherGcd), @@ -118,7 +118,7 @@ public class Rational { toCheckInput = false ) } - public operator fun div(other: Rational): Rational { + operator fun div(other: Rational): Rational { val denominatorsGcd = gcd(denominator, other.denominator) val numeratorsGcd = gcd(numerator, other.numerator) return Rational( @@ -126,7 +126,7 @@ public class Rational { (denominator / denominatorsGcd) * (other.numerator / numeratorsGcd) ) } - public operator fun div(other: Int): Rational { + operator fun div(other: Int): Rational { val other = other.toLong() val numeratorAndOtherGcd = gcd(numerator, other) return Rational( @@ -135,7 +135,7 @@ public class Rational { toCheckInput = false ) } - public operator fun div(other: Long): Rational { + operator fun div(other: Long): Rational { val numeratorAndOtherGcd = gcd(numerator, other) return Rational( numerator / numeratorAndOtherGcd, @@ -158,7 +158,7 @@ public class Rational { @Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE") @OptIn(UnstableKMathAPI::class) -public object RationalField : Field, NumbersAddOps { +object RationalField : Field, NumbersAddOps { override inline val zero: Rational get() = Rational.ZERO override inline val one: Rational get() = Rational.ONE diff --git a/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt similarity index 92% rename from test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt rename to kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt index 5d0b77aa8..4ef87f736 100644 --- a/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt @@ -13,7 +13,7 @@ import kotlin.test.assertEquals import kotlin.test.assertFailsWith -public fun assertContentEquals( +fun assertContentEquals( expected: Map, actual: Map, absoluteTolerance: Double, @@ -23,7 +23,7 @@ public fun assertContentEquals( for ((key, expectedValue) in expected) assertEquals(expectedValue, actual[key]!!, absoluteTolerance, message) } -public fun assertEquals( +fun assertEquals( expected: NumberedPolynomial, actual: NumberedPolynomial, absoluteTolerance: Double, @@ -37,7 +37,7 @@ public fun assertEquals( ) } -public fun assertEquals( +fun assertEquals( expected: LabeledPolynomial, actual: LabeledPolynomial, absoluteTolerance: Double, @@ -51,7 +51,7 @@ public fun assertEquals( ) } -public fun assertEquals( +fun assertEquals( expected: NumberedRationalFunction, actual: NumberedRationalFunction, absoluteTolerance: Double, @@ -71,7 +71,7 @@ public fun assertEquals( ) } -public fun assertEquals( +fun assertEquals( expected: LabeledRationalFunction, actual: LabeledRationalFunction, absoluteTolerance: Double, @@ -91,7 +91,7 @@ public fun assertEquals( ) } -public inline fun assertFailsWithTypeAndMessage( +inline fun assertFailsWithTypeAndMessage( expectedMessage: String? = null, assertionMessage: String? = null, block: () -> Unit diff --git a/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/misc.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/misc.kt similarity index 58% rename from test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/misc.kt rename to kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/misc.kt index 051fc0f37..93c3f8ea5 100644 --- a/test-utils-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/misc.kt +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/misc.kt @@ -9,11 +9,11 @@ import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.expressions.symbol -public val o: Rational = Rational(0) +val o: Rational = Rational(0) -public val x: Symbol by symbol -public val y: Symbol by symbol -public val z: Symbol by symbol -public val t: Symbol by symbol -public val s: Symbol by symbol -public val iota: Symbol by symbol \ No newline at end of file +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 bdd83d04e..336e1c36b 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -26,9 +26,7 @@ include( ":kmath-core", ":kmath-coroutines", ":kmath-functions", - ":test-utils-functions", ":kmath-polynomial", - ":test-utils-polynomial", ":kmath-histograms", ":kmath-commons", ":kmath-viktor", diff --git a/test-utils-functions/build.gradle.kts b/test-utils-functions/build.gradle.kts deleted file mode 100644 index 8476abecc..000000000 --- a/test-utils-functions/build.gradle.kts +++ /dev/null @@ -1,14 +0,0 @@ -plugins { - id("ru.mipt.npm.gradle.mpp") - id("ru.mipt.npm.gradle.native") -} - -kotlin.sourceSets { - commonMain { - dependencies { - api(projects.kmathCore) - api(projects.kmathFunctions) - api(kotlin("test")) - } - } -} diff --git a/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt b/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt deleted file mode 100644 index 5cf82996f..000000000 --- a/test-utils-functions/src/commonMain/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.functions.testUtils - -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith - - -public 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/test-utils-polynomial/build.gradle.kts b/test-utils-polynomial/build.gradle.kts deleted file mode 100644 index e10e1f2b1..000000000 --- a/test-utils-polynomial/build.gradle.kts +++ /dev/null @@ -1,14 +0,0 @@ -plugins { - id("ru.mipt.npm.gradle.mpp") - id("ru.mipt.npm.gradle.native") -} - -kotlin.sourceSets { - commonMain { - dependencies { - api(projects.kmathCore) - api(projects.kmathPolynomial) - api(kotlin("test")) - } - } -} -- 2.34.1 From 99c7174802e263d1961322a658d85b5e0da9d0a4 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sat, 16 Jul 2022 20:55:10 +0300 Subject: [PATCH 147/275] Turn Polynomial data class back. --- .../kotlin/space/kscience/kmath/functions/Polynomial.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 1e811d3ba..b57697dd9 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -10,7 +10,6 @@ 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.jvm.JvmInline import kotlin.math.max import kotlin.math.min @@ -20,8 +19,7 @@ import kotlin.math.min * * @param C the type of constants. */ -@JvmInline -public value class Polynomial( +public data class Polynomial( /** * List that contains coefficients of the polynomial. * -- 2.34.1 From 2d86cf1cc7e6294185038b2b34fc08c7bd17b040 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sat, 16 Jul 2022 21:55:35 +0300 Subject: [PATCH 148/275] Remove power overriding and algebraic stub. --- .../kscience/kmath/functions/Polynomial.kt | 4 - .../kscience/kmath/functions/algebraicStub.kt | 51 ------- .../kmath/functions/AlgebraicStubTest.kt | 129 ------------------ 3 files changed, 184 deletions(-) delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt delete mode 100644 kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index b57697dd9..9275ff8eb 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -247,10 +247,6 @@ public open class PolynomialSpace( ) } } - /** - * Raises [arg] to the integer power [exponent]. - */ // TODO: To optimize boxing - override fun power(arg: Polynomial, exponent: UInt): Polynomial = exponentiateBySquaring(arg, exponent) /** * Instance of zero polynomial (zero of the polynomial ring). diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt deleted file mode 100644 index 5eb1af4dc..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.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 -/** - * 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-functions/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt deleted file mode 100644 index 5782292b1..000000000 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.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_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)" - ) - } - } -} \ No newline at end of file -- 2.34.1 From f48e4483cc282730f6d7b6e9bddbb47046360682 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sat, 16 Jul 2022 22:21:13 +0300 Subject: [PATCH 149/275] Last cosmetic changes. --- .../kscience/kmath/functions/Polynomial.kt | 81 +++++++++---------- .../kmath/functions/polynomialUtil.kt | 4 +- 2 files changed, 39 insertions(+), 46 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 9275ff8eb..1f9bab52c 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -50,7 +50,7 @@ public data class Polynomial( */ public val coefficients: List ) { - override fun toString(): String = "ListPolynomial$coefficients" + override fun toString(): String = "Polynomial$coefficients" } /** @@ -63,7 +63,7 @@ public data class Polynomial( */ public open class PolynomialSpace( /** - * Underlying ring of constants. Its operations on constants are inherited by local operations on constants. + * Underlying ring of constants. Its operations on constants are used by local operations on constants and polynomials. */ public val ring: A, ) : Ring>, ScaleOperations> where A : Ring, A : ScaleOperations { @@ -191,61 +191,54 @@ public open class PolynomialSpace( /** * Returns negation of the polynomial. */ - public override operator fun Polynomial.unaryMinus(): Polynomial = - with(ring) { - Polynomial(coefficients.map { -it }) - } + public override operator fun Polynomial.unaryMinus(): Polynomial = ring { + Polynomial(coefficients.map { -it }) + } /** * Returns sum of the polynomials. */ - public override operator fun Polynomial.plus(other: Polynomial): Polynomial { - with(ring) { - val thisDegree = degree - val otherDegree = other.degree - return Polynomial( - List(max(thisDegree, otherDegree) + 1) { - when { - it > thisDegree -> other.coefficients[it] - it > otherDegree -> coefficients[it] - else -> coefficients[it] + other.coefficients[it] - } + public override operator fun Polynomial.plus(other: Polynomial): Polynomial = ring { + val thisDegree = degree + val otherDegree = other.degree + return Polynomial( + List(max(thisDegree, otherDegree) + 1) { + when { + it > thisDegree -> other.coefficients[it] + it > otherDegree -> coefficients[it] + else -> coefficients[it] + other.coefficients[it] } - ) - } + } + ) } /** * Returns difference of the polynomials. */ - public override operator fun Polynomial.minus(other: Polynomial): Polynomial { - with(ring) { - val thisDegree = degree - val otherDegree = other.degree - return Polynomial( - List(max(thisDegree, otherDegree) + 1) { - when { - it > thisDegree -> -other.coefficients[it] - it > otherDegree -> coefficients[it] - else -> coefficients[it] - other.coefficients[it] - } + public override operator fun Polynomial.minus(other: Polynomial): Polynomial = ring { + val thisDegree = degree + val otherDegree = other.degree + return Polynomial( + List(max(thisDegree, otherDegree) + 1) { + when { + it > thisDegree -> -other.coefficients[it] + it > otherDegree -> coefficients[it] + else -> coefficients[it] - other.coefficients[it] } - ) - } + } + ) } /** * Returns product of the polynomials. */ - public override operator fun Polynomial.times(other: Polynomial): Polynomial { - with(ring) { - val thisDegree = degree - val otherDegree = other.degree - return Polynomial( - List(thisDegree + otherDegree + 1) { d -> - (max(0, d - otherDegree)..min(thisDegree, d)) - .map { coefficients[it] * other.coefficients[d - it] } - .reduce { acc, rational -> acc + rational } - } - ) - } + public override operator fun Polynomial.times(other: Polynomial): Polynomial = ring { + val thisDegree = degree + val otherDegree = other.degree + return Polynomial( + List(thisDegree + otherDegree + 1) { d -> + (max(0, d - otherDegree)..min(thisDegree, d)) + .map { coefficients[it] * other.coefficients[d - it] } + .reduce { acc, rational -> acc + rational } + } + ) } /** diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt index f745bf6e4..c9377a6c1 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt @@ -91,7 +91,7 @@ public fun Polynomial.integrate( public fun > Polynomial.integrate( ring: Field, range: ClosedRange, -): C { +): C = ring { val antiderivative = integrate(ring) - return ring { antiderivative.value(ring, range.endInclusive) - antiderivative.value(ring, range.start) } + return antiderivative.value(ring, range.endInclusive) - antiderivative.value(ring, range.start) } \ No newline at end of file -- 2.34.1 From 7de157ce24da9346f323c3226ce93d0355d996bf Mon Sep 17 00:00:00 2001 From: Erik Schouten Date: Sun, 17 Jul 2022 14:21:12 +0200 Subject: [PATCH 150/275] Re-introduce line/straight segment, rename components to start/end --- .../trajectory/dubins/DubinsPathFactory.kt | 124 +++++++++--------- .../kscience/kmath/trajectory/segments/Arc.kt | 12 +- .../kmath/trajectory/segments/Line.kt | 23 ---- .../kmath/trajectory/segments/Straight.kt | 18 +++ .../space/kscience/kmath/trajectory/Math.kt | 13 +- .../kmath/trajectory/dubins/DubinsTests.kt | 20 ++- .../kmath/trajectory/segments/LineTests.kt | 15 +-- 7 files changed, 106 insertions(+), 119 deletions(-) delete mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Line.kt create mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Straight.kt diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPathFactory.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPathFactory.kt index 91287b952..04c639576 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPathFactory.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPathFactory.kt @@ -6,21 +6,18 @@ package space.kscience.kmath.trajectory.dubins import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo -import space.kscience.kmath.geometry.Line2D import space.kscience.kmath.geometry.Vector2D -import space.kscience.kmath.trajectory.segments.Arc -import space.kscience.kmath.trajectory.segments.LineSegment +import space.kscience.kmath.trajectory.segments.* import space.kscience.kmath.trajectory.segments.components.Circle import space.kscience.kmath.trajectory.segments.components.Pose2D -import space.kscience.kmath.trajectory.segments.length -import space.kscience.kmath.trajectory.segments.theta +import kotlin.math.PI import kotlin.math.acos import kotlin.math.cos import kotlin.math.sin public class DubinsPathFactory( - private val base: Pose2D, - private val direction: Pose2D, + private val start: Pose2D, + private val end: Pose2D, private val turningRadius: Double ) { @@ -30,9 +27,9 @@ public class DubinsPathFactory( public val rlr: DubinsPath? get() { - val c1 = base.getRightCircle(turningRadius) - val c2 = direction.getRightCircle(turningRadius) - val centers = Line2D(c1.center, c2.center) + val c1 = start.getRightCircle(turningRadius) + val c2 = end.getRightCircle(turningRadius) + val centers = Straight(c1.center, c2.center) if (centers.length > turningRadius * 4) return null var theta = theta(centers.theta - acos(centers.length / (turningRadius * 4))) @@ -45,17 +42,17 @@ public class DubinsPathFactory( dX = turningRadius * sin(theta) dY = turningRadius * cos(theta) val p2 = Vector2D(e.center.x + dX, e.center.y + dY) - val a1 = Arc(c1.center, base, p1, Arc.Direction.RIGHT) + val a1 = Arc(c1.center, start, p1, Arc.Direction.RIGHT) val a2 = Arc(e.center, p1, p2, Arc.Direction.LEFT) - val a3 = Arc(c2.center, p2, direction, Arc.Direction.RIGHT) + val a3 = Arc(c2.center, p2, end, Arc.Direction.RIGHT) return DubinsPath(a1, a2, a3) } private val lrl: DubinsPath? get() { - val c1 = base.getLeftCircle(turningRadius) - val c2 = direction.getLeftCircle(turningRadius) - val centers = Line2D(c1.center, c2.center) + val c1 = start.getLeftCircle(turningRadius) + val c2 = end.getLeftCircle(turningRadius) + val centers = Straight(c1.center, c2.center) if (centers.length > turningRadius * 4) return null var theta = theta(centers.theta + acos(centers.length / (turningRadius * 4))) @@ -68,54 +65,54 @@ public class DubinsPathFactory( dX = turningRadius * sin(theta) dY = turningRadius * cos(theta) val p2 = Vector2D(e.center.x + dX, e.center.y + dY) - val a1 = Arc(c1.center, base, p1, Arc.Direction.LEFT) + val a1 = Arc(c1.center, start, p1, Arc.Direction.LEFT) val a2 = Arc(e.center, p1, p2, Arc.Direction.RIGHT) - val a3 = Arc(c2.center, p2, direction, Arc.Direction.LEFT) + val a3 = Arc(c2.center, p2, end, Arc.Direction.LEFT) return DubinsPath(a1, a2, a3) } public val rsr: DubinsPath get() { - val c1 = base.getRightCircle(turningRadius) - val c2 = direction.getRightCircle(turningRadius) - val l = leftOuterTangent(c1, c2) - val a1 = Arc(c1.center, base, l.base, Arc.Direction.RIGHT) - val a3 = Arc(c2.center, l.direction, direction, Arc.Direction.RIGHT) - return DubinsPath(a1, LineSegment(l), a3) + val c1 = start.getRightCircle(turningRadius) + val c2 = end.getRightCircle(turningRadius) + val s = leftOuterTangent(c1, c2) + val a1 = Arc(c1.center, start, s.start, Arc.Direction.RIGHT) + val a3 = Arc(c2.center, s.end, end, Arc.Direction.RIGHT) + return DubinsPath(a1, s, a3) } public val lsl: DubinsPath get() { - val c1 = base.getLeftCircle(turningRadius) - val c2 = direction.getLeftCircle(turningRadius) - val l = rightOuterTangent(c1, c2) - val a1 = Arc(c1.center, base, l.base, Arc.Direction.LEFT) - val a3 = Arc(c2.center, l.direction, direction, Arc.Direction.LEFT) - return DubinsPath(a1, LineSegment(l), a3) + val c1 = start.getLeftCircle(turningRadius) + val c2 = end.getLeftCircle(turningRadius) + val s = rightOuterTangent(c1, c2) + val a1 = Arc(c1.center, start, s.start, Arc.Direction.LEFT) + val a3 = Arc(c2.center, s.end, end, Arc.Direction.LEFT) + return DubinsPath(a1, s, a3) } public val rsl: DubinsPath? get() { - val c1 = base.getRightCircle(turningRadius) - val c2 = direction.getLeftCircle(turningRadius) - val l = rightInnerTangent(c1, c2) - if (c1.center.distanceTo(c2.center) < turningRadius * 2 || l == null) return null + val c1 = start.getRightCircle(turningRadius) + val c2 = end.getLeftCircle(turningRadius) + val s = rightInnerTangent(c1, c2) + if (c1.center.distanceTo(c2.center) < turningRadius * 2 || s == null) return null - val a1 = Arc(c1.center, base, l.base, Arc.Direction.RIGHT) - val a3 = Arc(c2.center, l.direction, direction, Arc.Direction.LEFT) - return DubinsPath(a1, LineSegment(l), a3) + val a1 = Arc(c1.center, start, s.start, Arc.Direction.RIGHT) + val a3 = Arc(c2.center, s.end, end, Arc.Direction.LEFT) + return DubinsPath(a1, s, a3) } public val lsr: DubinsPath? get() { - val c1 = base.getLeftCircle(turningRadius) - val c2 = direction.getRightCircle(turningRadius) - val l = leftInnerTangent(c1, c2) - if (c1.center.distanceTo(c2.center) < turningRadius * 2 || l == null) return null + val c1 = start.getLeftCircle(turningRadius) + val c2 = end.getRightCircle(turningRadius) + val s = leftInnerTangent(c1, c2) + if (c1.center.distanceTo(c2.center) < turningRadius * 2 || s == null) return null - val a1 = Arc(c1.center, base, l.base, Arc.Direction.LEFT) - val a3 = Arc(c2.center, l.direction, direction, Arc.Direction.RIGHT) - return DubinsPath(a1, LineSegment(l), a3) + val a1 = Arc(c1.center, start, s.start, Arc.Direction.LEFT) + val a3 = Arc(c2.center, s.end, end, Arc.Direction.RIGHT) + return DubinsPath(a1, s, a3) } } @@ -133,8 +130,8 @@ private fun Pose2D.getTangentCircles(radius: Double): Pair { private fun leftOuterTangent(a: Circle, b: Circle) = outerTangent(a, b, SIDE.LEFT) private fun rightOuterTangent(a: Circle, b: Circle) = outerTangent(a, b, SIDE.RIGHT) -private fun outerTangent(a: Circle, b: Circle, side: SIDE): Line2D { - val centers = Line2D(a.center, b.center) +private fun outerTangent(a: Circle, b: Circle, side: SIDE): Straight { + val centers = Straight(a.center, b.center) val p1 = when (side) { SIDE.LEFT -> Vector2D( a.center.x - a.radius * cos(centers.theta), @@ -145,29 +142,28 @@ private fun outerTangent(a: Circle, b: Circle, side: SIDE): Line2D { a.center.y - a.radius * sin(centers.theta) ) } - return Line2D( + return Straight( p1, - Vector2D(p1.x + (centers.direction.x - centers.base.x), p1.y + (centers.direction.y - centers.base.y)) + Vector2D(p1.x + (centers.end.x - centers.start.x), p1.y + (centers.end.y - centers.start.y)) ) } private fun leftInnerTangent(base: Circle, direction: Circle) = innerTangent(base, direction, SIDE.LEFT) private fun rightInnerTangent(base: Circle, direction: Circle) = innerTangent(base, direction, SIDE.RIGHT) -private fun innerTangent(base: Circle, direction: Circle, side: SIDE): Line2D? { - val centers = Line2D(base.center, direction.center) - return if (centers.length > base.radius * 2) { - val angle = theta( - when (side) { - SIDE.LEFT -> centers.theta + acos(base.radius * 2 / centers.length) - SIDE.RIGHT -> centers.theta - acos(base.radius * 2 / centers.length) - } - ) - val dX = base.radius * sin(angle) - val dY = base.radius * cos(angle) - val p1 = Vector2D(base.center.x + dX, base.center.y + dY) - val p2 = Vector2D(direction.center.x - dX, direction.center.y - dY) - Line2D(p1, p2) - } else { - null - } +private fun innerTangent(base: Circle, direction: Circle, side: SIDE): Straight? { + val centers = Straight(base.center, direction.center) + if (centers.length < base.radius * 2) return null + val angle = theta( + when (side) { + SIDE.LEFT -> centers.theta + acos(base.radius * 2 / centers.length) + SIDE.RIGHT -> centers.theta - acos(base.radius * 2 / centers.length) + } + ) + val dX = base.radius * sin(angle) + val dY = base.radius * cos(angle) + val p1 = Vector2D(base.center.x + dX, base.center.y + dY) + val p2 = Vector2D(direction.center.x - dX, direction.center.y - dY) + return Straight(p1, p2) } + +internal fun theta(theta: Double) = (theta + (2 * PI)) % (2 * PI) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt index b8a81a070..b5e091db7 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt @@ -1,8 +1,8 @@ package space.kscience.kmath.trajectory.segments import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo -import space.kscience.kmath.geometry.Line2D import space.kscience.kmath.geometry.Vector2D +import space.kscience.kmath.trajectory.dubins.theta import space.kscience.kmath.trajectory.segments.components.Circle import space.kscience.kmath.trajectory.segments.components.Pose2D import kotlin.math.PI @@ -14,11 +14,11 @@ public class Arc( internal val direction: Direction ) : Circle(center, center.distanceTo(a)), Segment { - private val l1 = Line2D(center, a) - private val l2 = Line2D(center, b) + private val s1 = Straight(center, a) + private val s2 = Straight(center, b) - internal val pose1 = calculatePose(a, l1.theta) - internal val pose2 = calculatePose(b, l2.theta) + internal val pose1 = calculatePose(a, s1.theta) + internal val pose2 = calculatePose(b, s2.theta) private val angle = calculateAngle() override val length: Double = calculateLength() @@ -26,7 +26,7 @@ public class Arc( LEFT, RIGHT } - private fun calculateAngle() = theta(if (direction == Direction.LEFT) l1.theta - l2.theta else l2.theta - l1.theta) + private fun calculateAngle() = theta(if (direction == Direction.LEFT) s1.theta - s2.theta else s2.theta - s1.theta) private fun calculateLength(): Double { val proportion = angle / (2 * PI) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Line.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Line.kt deleted file mode 100644 index 0e23b27f1..000000000 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Line.kt +++ /dev/null @@ -1,23 +0,0 @@ -package space.kscience.kmath.trajectory.segments - -import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo -import space.kscience.kmath.geometry.Line2D -import space.kscience.kmath.operations.DoubleField.pow -import kotlin.math.PI -import kotlin.math.atan2 -import kotlin.math.sqrt - -public data class LineSegment( - internal val line: Line2D -) : Segment { - override val length: Double - get() = line.length -} - -internal val Line2D.theta: Double - get() = theta(atan2(direction.x - base.x, direction.y - base.y)) - -internal val Line2D.length: Double - get() = base.distanceTo(direction) - -internal fun theta(theta: Double) = (theta + (2 * PI)) % (2 * PI) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Straight.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Straight.kt new file mode 100644 index 000000000..444025d83 --- /dev/null +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Straight.kt @@ -0,0 +1,18 @@ +package space.kscience.kmath.trajectory.segments + +import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo +import space.kscience.kmath.geometry.Vector2D +import space.kscience.kmath.trajectory.dubins.theta +import kotlin.math.PI +import kotlin.math.atan2 + +public data class Straight( + internal val start: Vector2D, + internal val end: Vector2D +) : Segment { + override val length: Double + get() = start.distanceTo(end) + + internal val theta: Double + get() = theta(atan2(end.x - start.x, end.y - start.y)) +} 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 f52bb56f2..92b2f1df9 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 @@ -1,9 +1,8 @@ package space.kscience.kmath.trajectory -import space.kscience.kmath.geometry.Line2D import space.kscience.kmath.geometry.Vector2D +import space.kscience.kmath.trajectory.segments.Straight import space.kscience.kmath.trajectory.segments.components.Pose2D -import space.kscience.kmath.trajectory.segments.theta import kotlin.math.PI import kotlin.math.abs import kotlin.math.sin @@ -15,13 +14,13 @@ 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 Line2D.inverse() = Line2D(direction, base) -fun Line2D.shift(shift: Int, width: Double): Line2D { +fun Straight.inverse() = Straight(end, start) +fun Straight.shift(shift: Int, width: Double): Straight { val dX = width * sin(inverse().theta) val dY = width * sin(theta) - return Line2D( - Vector2D(base.x - dX * shift, base.y - dY * shift), - Vector2D(direction.x - dX * shift, direction.y - dY * shift) + return Straight( + Vector2D(start.x - dX * shift, start.y - dY * shift), + Vector2D(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 583e7a4e0..efe35e5d8 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,15 +6,13 @@ package space.kscience.kmath.trajectory.dubins import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo -import space.kscience.kmath.geometry.Line2D import space.kscience.kmath.geometry.Vector2D import space.kscience.kmath.trajectory.segments.Arc -import space.kscience.kmath.trajectory.segments.LineSegment import space.kscience.kmath.trajectory.equalFloat import space.kscience.kmath.trajectory.equalsFloat import space.kscience.kmath.trajectory.inverse +import space.kscience.kmath.trajectory.segments.Straight import space.kscience.kmath.trajectory.segments.components.Pose2D -import space.kscience.kmath.trajectory.segments.theta import space.kscience.kmath.trajectory.shift import kotlin.test.Test import kotlin.test.assertNotNull @@ -25,11 +23,11 @@ class DubinsTests { @Test fun dubinsTest() { - val line = Line2D(Vector2D(0.0, 0.0), Vector2D(100.0, 100.0)) - val lineP1 = line.shift(1, 10.0).inverse() + val straight = Straight(Vector2D(0.0, 0.0), Vector2D(100.0, 100.0)) + val lineP1 = straight.shift(1, 10.0).inverse() - val start = Pose2D(line.direction, line.theta) - val end = Pose2D(lineP1.base, lineP1.theta) + val start = Pose2D(straight.end, straight.theta) + val end = Pose2D(lineP1.start, lineP1.theta) val radius = 2.0 val dubins = DubinsPathFactory(start, end, radius) @@ -58,10 +56,10 @@ class DubinsTests { val b = path.b as Arc assertTrue(path.a.pose2.equalsFloat(b.pose1)) assertTrue(path.c.pose1.equalsFloat(b.pose2)) - } else if (path.b is LineSegment) { - val b = (path.b as LineSegment).line - assertTrue(path.a.pose2.equalsFloat(Pose2D(b.base, b.theta))) - assertTrue(path.c.pose1.equalsFloat(Pose2D(b.direction, b.theta))) + } else if (path.b is Straight) { + val b = path.b as Straight + assertTrue(path.a.pose2.equalsFloat(Pose2D(b.start, b.theta))) + assertTrue(path.c.pose1.equalsFloat(Pose2D(b.end, b.theta))) } } } 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 30f5ef6d8..e8184e178 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 @@ -1,7 +1,6 @@ package space.kscience.kmath.trajectory.segments import space.kscience.kmath.geometry.Euclidean2DSpace -import space.kscience.kmath.geometry.Line2D import space.kscience.kmath.geometry.Vector2D import space.kscience.kmath.trajectory.radiansToDegrees import kotlin.math.pow @@ -13,21 +12,21 @@ class LineTests { @Test fun lineTest() { - val line = Line2D(Vector2D(0.0, 0.0), Vector2D(100.0, 100.0)) - assertEquals(sqrt(100.0.pow(2) + 100.0.pow(2)), line.length) - assertEquals(45.0, line.theta.radiansToDegrees()) + val straight = Straight(Vector2D(0.0, 0.0), Vector2D(100.0, 100.0)) + assertEquals(sqrt(100.0.pow(2) + 100.0.pow(2)), straight.length) + assertEquals(45.0, straight.theta.radiansToDegrees()) } @Test fun lineAngleTest() { val zero = Vector2D(0.0, 0.0) - val north = Line2D(Euclidean2DSpace.zero, Vector2D(0.0, 2.0)) + val north = Straight(Euclidean2DSpace.zero, Vector2D(0.0, 2.0)) assertEquals(0.0, north.theta.radiansToDegrees()) - val east = Line2D(Euclidean2DSpace.zero, Vector2D(2.0, 0.0)) + val east = Straight(Euclidean2DSpace.zero, Vector2D(2.0, 0.0)) assertEquals(90.0, east.theta.radiansToDegrees()) - val south = Line2D(Euclidean2DSpace.zero, Vector2D(0.0, -2.0)) + val south = Straight(Euclidean2DSpace.zero, Vector2D(0.0, -2.0)) assertEquals(180.0, south.theta.radiansToDegrees()) - val west = Line2D(Euclidean2DSpace.zero, Vector2D(-2.0, 0.0)) + val west = Straight(Euclidean2DSpace.zero, Vector2D(-2.0, 0.0)) assertEquals(270.0, west.theta.radiansToDegrees()) } } -- 2.34.1 From 3260c3d17146226f465aa98a5fc6f8a7cb4262cd Mon Sep 17 00:00:00 2001 From: Erik Schouten Date: Sun, 17 Jul 2022 14:39:43 +0200 Subject: [PATCH 151/275] Pose2D facrtory function --- .../space/kscience/kmath/trajectory/segments/Arc.kt | 12 +++++++----- .../kmath/trajectory/segments/components/Pose2D.kt | 6 +++--- .../kscience/kmath/trajectory/dubins/DubinsTests.kt | 10 +++++----- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt index b5e091db7..fe101f359 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt @@ -34,9 +34,11 @@ public class Arc( } private fun calculatePose(vector: Vector2D, theta: Double): Pose2D = - if (direction == Direction.LEFT) { - Pose2D(vector.x, vector.y, theta(theta - PI / 2)) - } else { - Pose2D(vector.x, vector.y, theta(theta + PI / 2)) - } + Pose2D.of( + vector, + when (direction) { + Direction.LEFT -> theta(theta - PI / 2) + Direction.RIGHT -> theta(theta + PI / 2) + } + ) } diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/components/Pose2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/components/Pose2D.kt index d00dfbd96..c49da3187 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/components/Pose2D.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/components/Pose2D.kt @@ -1,13 +1,13 @@ package space.kscience.kmath.trajectory.segments.components import space.kscience.kmath.geometry.Vector2D -import kotlin.math.cos -import kotlin.math.sin public data class Pose2D( override val x: Double, override val y: Double, public val theta: Double ) : Vector2D { - internal constructor(vector: Vector2D, theta: Double) : this(vector.x, vector.y, theta) + internal companion object { + internal fun of(vector: Vector2D, theta: Double) = Pose2D(vector.x, vector.y, theta) + } } 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 efe35e5d8..025aab2b7 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 @@ -7,10 +7,10 @@ package space.kscience.kmath.trajectory.dubins import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo import space.kscience.kmath.geometry.Vector2D -import space.kscience.kmath.trajectory.segments.Arc import space.kscience.kmath.trajectory.equalFloat import space.kscience.kmath.trajectory.equalsFloat import space.kscience.kmath.trajectory.inverse +import space.kscience.kmath.trajectory.segments.Arc import space.kscience.kmath.trajectory.segments.Straight import space.kscience.kmath.trajectory.segments.components.Pose2D import space.kscience.kmath.trajectory.shift @@ -26,8 +26,8 @@ class DubinsTests { val straight = Straight(Vector2D(0.0, 0.0), Vector2D(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.of(straight.end, straight.theta) + val end = Pose2D.of(lineP1.start, lineP1.theta) val radius = 2.0 val dubins = DubinsPathFactory(start, end, radius) @@ -58,8 +58,8 @@ class DubinsTests { assertTrue(path.c.pose1.equalsFloat(b.pose2)) } else if (path.b is Straight) { val b = path.b as Straight - assertTrue(path.a.pose2.equalsFloat(Pose2D(b.start, b.theta))) - assertTrue(path.c.pose1.equalsFloat(Pose2D(b.end, b.theta))) + assertTrue(path.a.pose2.equalsFloat(Pose2D.of(b.start, b.theta))) + assertTrue(path.c.pose1.equalsFloat(Pose2D.of(b.end, b.theta))) } } } -- 2.34.1 From 8faa312424f37bf6aa4b6db3c33e166709c346d2 Mon Sep 17 00:00:00 2001 From: Erik Schouten Date: Sun, 17 Jul 2022 14:56:21 +0200 Subject: [PATCH 152/275] Dubins factory functions --- .../kmath/trajectory/dubins/DubinsPath.kt | 106 +++++++++++ .../trajectory/dubins/DubinsPathFactory.kt | 169 ------------------ .../trajectory/dubins/TrajectoryFunctions.kt | 67 +++++++ .../kmath/trajectory/dubins/DubinsTests.kt | 4 +- 4 files changed, 175 insertions(+), 171 deletions(-) delete mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPathFactory.kt create mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/TrajectoryFunctions.kt diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPath.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPath.kt index 005d7fd60..ad67fa11d 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPath.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPath.kt @@ -5,8 +5,16 @@ package space.kscience.kmath.trajectory.dubins +import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo +import space.kscience.kmath.geometry.Vector2D import space.kscience.kmath.trajectory.segments.Arc import space.kscience.kmath.trajectory.segments.Segment +import space.kscience.kmath.trajectory.segments.Straight +import space.kscience.kmath.trajectory.segments.components.Circle +import space.kscience.kmath.trajectory.segments.components.Pose2D +import kotlin.math.acos +import kotlin.math.cos +import kotlin.math.sin public class DubinsPath( public val a: Arc, @@ -27,4 +35,102 @@ public class DubinsPath( public enum class TYPE { RLR, LRL, RSR, LSL, RSL, LSR } + + public companion object { + public fun all(start: Pose2D, end: Pose2D, turningRadius: Double): List = + listOfNotNull( + rlr(start, end, turningRadius), + lrl(start, end, turningRadius), + rsr(start, end, turningRadius), + lsl(start, end, turningRadius), + rsl(start, end, turningRadius), + lsr(start, end, turningRadius) + ) + public fun shortest(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath = + all(start, end, turningRadius).minByOrNull { it.length }!! + + public fun rlr(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath? { + val c1 = start.getRightCircle(turningRadius) + val c2 = end.getRightCircle(turningRadius) + val centers = Straight(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 = Vector2D(c1.center.x + dX * 2, c1.center.y + dY * 2) + val e = Circle(p, turningRadius) + val p1 = Vector2D(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 = Vector2D(e.center.x + dX, e.center.y + dY) + val a1 = Arc(c1.center, start, p1, Arc.Direction.RIGHT) + val a2 = Arc(e.center, p1, p2, Arc.Direction.LEFT) + val a3 = Arc(c2.center, p2, end, Arc.Direction.RIGHT) + return DubinsPath(a1, a2, a3) + } + + public fun lrl(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath? { + val c1 = start.getLeftCircle(turningRadius) + val c2 = end.getLeftCircle(turningRadius) + val centers = Straight(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 = Vector2D(c1.center.x + dX * 2, c1.center.y + dY * 2) + val e = Circle(p, turningRadius) + val p1 = Vector2D(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 = Vector2D(e.center.x + dX, e.center.y + dY) + val a1 = Arc(c1.center, start, p1, Arc.Direction.LEFT) + val a2 = Arc(e.center, p1, p2, Arc.Direction.RIGHT) + val a3 = Arc(c2.center, p2, end, Arc.Direction.LEFT) + return DubinsPath(a1, a2, a3) + } + + public fun rsr(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath { + val c1 = start.getRightCircle(turningRadius) + val c2 = end.getRightCircle(turningRadius) + val s = leftOuterTangent(c1, c2) + val a1 = Arc(c1.center, start, s.start, Arc.Direction.RIGHT) + val a3 = Arc(c2.center, s.end, end, Arc.Direction.RIGHT) + return DubinsPath(a1, s, a3) + } + + public fun lsl(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath { + val c1 = start.getLeftCircle(turningRadius) + val c2 = end.getLeftCircle(turningRadius) + val s = rightOuterTangent(c1, c2) + val a1 = Arc(c1.center, start, s.start, Arc.Direction.LEFT) + val a3 = Arc(c2.center, s.end, end, Arc.Direction.LEFT) + return DubinsPath(a1, s, a3) + } + + public fun rsl(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath? { + val c1 = start.getRightCircle(turningRadius) + val c2 = end.getLeftCircle(turningRadius) + val s = rightInnerTangent(c1, c2) + if (c1.center.distanceTo(c2.center) < turningRadius * 2 || s == null) return null + + val a1 = Arc(c1.center, start, s.start, Arc.Direction.RIGHT) + val a3 = Arc(c2.center, s.end, end, Arc.Direction.LEFT) + return DubinsPath(a1, s, a3) + } + + public fun lsr(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath? { + val c1 = start.getLeftCircle(turningRadius) + val c2 = end.getRightCircle(turningRadius) + val s = leftInnerTangent(c1, c2) + if (c1.center.distanceTo(c2.center) < turningRadius * 2 || s == null) return null + + val a1 = Arc(c1.center, start, s.start, Arc.Direction.LEFT) + val a3 = Arc(c2.center, s.end, end, Arc.Direction.RIGHT) + return DubinsPath(a1, s, a3) + } + } } diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPathFactory.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPathFactory.kt deleted file mode 100644 index 04c639576..000000000 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPathFactory.kt +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.trajectory.dubins - -import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo -import space.kscience.kmath.geometry.Vector2D -import space.kscience.kmath.trajectory.segments.* -import space.kscience.kmath.trajectory.segments.components.Circle -import space.kscience.kmath.trajectory.segments.components.Pose2D -import kotlin.math.PI -import kotlin.math.acos -import kotlin.math.cos -import kotlin.math.sin - -public class DubinsPathFactory( - private val start: Pose2D, - private val end: Pose2D, - private val turningRadius: Double -) { - - public val all: List get() = listOfNotNull(rlr, lrl, rsr, lsl, rsl, lsr) - public val shortest: DubinsPath get() = all.minByOrNull { it.length }!! - public operator fun get(type: DubinsPath.TYPE): DubinsPath? = all.find { it.type == type } - - public val rlr: DubinsPath? - get() { - val c1 = start.getRightCircle(turningRadius) - val c2 = end.getRightCircle(turningRadius) - val centers = Straight(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 = Vector2D(c1.center.x + dX * 2, c1.center.y + dY * 2) - val e = Circle(p, turningRadius) - val p1 = Vector2D(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 = Vector2D(e.center.x + dX, e.center.y + dY) - val a1 = Arc(c1.center, start, p1, Arc.Direction.RIGHT) - val a2 = Arc(e.center, p1, p2, Arc.Direction.LEFT) - val a3 = Arc(c2.center, p2, end, Arc.Direction.RIGHT) - return DubinsPath(a1, a2, a3) - } - - private val lrl: DubinsPath? - get() { - val c1 = start.getLeftCircle(turningRadius) - val c2 = end.getLeftCircle(turningRadius) - val centers = Straight(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 = Vector2D(c1.center.x + dX * 2, c1.center.y + dY * 2) - val e = Circle(p, turningRadius) - val p1 = Vector2D(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 = Vector2D(e.center.x + dX, e.center.y + dY) - val a1 = Arc(c1.center, start, p1, Arc.Direction.LEFT) - val a2 = Arc(e.center, p1, p2, Arc.Direction.RIGHT) - val a3 = Arc(c2.center, p2, end, Arc.Direction.LEFT) - return DubinsPath(a1, a2, a3) - } - - public val rsr: DubinsPath - get() { - val c1 = start.getRightCircle(turningRadius) - val c2 = end.getRightCircle(turningRadius) - val s = leftOuterTangent(c1, c2) - val a1 = Arc(c1.center, start, s.start, Arc.Direction.RIGHT) - val a3 = Arc(c2.center, s.end, end, Arc.Direction.RIGHT) - return DubinsPath(a1, s, a3) - } - - public val lsl: DubinsPath - get() { - val c1 = start.getLeftCircle(turningRadius) - val c2 = end.getLeftCircle(turningRadius) - val s = rightOuterTangent(c1, c2) - val a1 = Arc(c1.center, start, s.start, Arc.Direction.LEFT) - val a3 = Arc(c2.center, s.end, end, Arc.Direction.LEFT) - return DubinsPath(a1, s, a3) - } - - public val rsl: DubinsPath? - get() { - val c1 = start.getRightCircle(turningRadius) - val c2 = end.getLeftCircle(turningRadius) - val s = rightInnerTangent(c1, c2) - if (c1.center.distanceTo(c2.center) < turningRadius * 2 || s == null) return null - - val a1 = Arc(c1.center, start, s.start, Arc.Direction.RIGHT) - val a3 = Arc(c2.center, s.end, end, Arc.Direction.LEFT) - return DubinsPath(a1, s, a3) - } - - public val lsr: DubinsPath? - get() { - val c1 = start.getLeftCircle(turningRadius) - val c2 = end.getRightCircle(turningRadius) - val s = leftInnerTangent(c1, c2) - if (c1.center.distanceTo(c2.center) < turningRadius * 2 || s == null) return null - - val a1 = Arc(c1.center, start, s.start, Arc.Direction.LEFT) - val a3 = Arc(c2.center, s.end, end, Arc.Direction.RIGHT) - return DubinsPath(a1, s, a3) - } -} - -private enum class SIDE { - LEFT, RIGHT -} - -private fun Pose2D.getLeftCircle(radius: Double): Circle = getTangentCircles(radius).first -private fun Pose2D.getRightCircle(radius: Double): Circle = getTangentCircles(radius).second -private fun Pose2D.getTangentCircles(radius: Double): Pair { - val dX = radius * cos(theta) - val dY = radius * sin(theta) - return Circle(Vector2D(x - dX, y + dY), radius) to Circle(Vector2D(x + dX, y - dY), radius) -} - -private fun leftOuterTangent(a: Circle, b: Circle) = outerTangent(a, b, SIDE.LEFT) -private fun rightOuterTangent(a: Circle, b: Circle) = outerTangent(a, b, SIDE.RIGHT) -private fun outerTangent(a: Circle, b: Circle, side: SIDE): Straight { - val centers = Straight(a.center, b.center) - val p1 = when (side) { - SIDE.LEFT -> Vector2D( - a.center.x - a.radius * cos(centers.theta), - a.center.y + a.radius * sin(centers.theta) - ) - SIDE.RIGHT -> Vector2D( - a.center.x + a.radius * cos(centers.theta), - a.center.y - a.radius * sin(centers.theta) - ) - } - return Straight( - p1, - Vector2D(p1.x + (centers.end.x - centers.start.x), p1.y + (centers.end.y - centers.start.y)) - ) -} - -private fun leftInnerTangent(base: Circle, direction: Circle) = innerTangent(base, direction, SIDE.LEFT) -private fun rightInnerTangent(base: Circle, direction: Circle) = innerTangent(base, direction, SIDE.RIGHT) -private fun innerTangent(base: Circle, direction: Circle, side: SIDE): Straight? { - val centers = Straight(base.center, direction.center) - if (centers.length < base.radius * 2) return null - val angle = theta( - when (side) { - SIDE.LEFT -> centers.theta + acos(base.radius * 2 / centers.length) - SIDE.RIGHT -> centers.theta - acos(base.radius * 2 / centers.length) - } - ) - val dX = base.radius * sin(angle) - val dY = base.radius * cos(angle) - val p1 = Vector2D(base.center.x + dX, base.center.y + dY) - val p2 = Vector2D(direction.center.x - dX, direction.center.y - dY) - return Straight(p1, p2) -} - -internal fun theta(theta: Double) = (theta + (2 * PI)) % (2 * PI) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/TrajectoryFunctions.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/TrajectoryFunctions.kt new file mode 100644 index 000000000..547cb99fc --- /dev/null +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/TrajectoryFunctions.kt @@ -0,0 +1,67 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.trajectory.dubins + +import space.kscience.kmath.geometry.Vector2D +import space.kscience.kmath.trajectory.segments.Straight +import space.kscience.kmath.trajectory.segments.components.Circle +import space.kscience.kmath.trajectory.segments.components.Pose2D +import kotlin.math.PI +import kotlin.math.acos +import kotlin.math.cos +import kotlin.math.sin + +private enum class SIDE { + LEFT, RIGHT +} + +internal fun Pose2D.getLeftCircle(radius: Double): Circle = getTangentCircles(radius).first +internal fun Pose2D.getRightCircle(radius: Double): Circle = getTangentCircles(radius).second +internal fun Pose2D.getTangentCircles(radius: Double): Pair { + val dX = radius * cos(theta) + val dY = radius * sin(theta) + return Circle(Vector2D(x - dX, y + dY), radius) to Circle(Vector2D(x + dX, y - dY), radius) +} + +internal fun leftOuterTangent(a: Circle, b: Circle) = outerTangent(a, b, SIDE.LEFT) +internal fun rightOuterTangent(a: Circle, b: Circle) = outerTangent(a, b, SIDE.RIGHT) +private fun outerTangent(a: Circle, b: Circle, side: SIDE): Straight { + val centers = Straight(a.center, b.center) + val p1 = when (side) { + SIDE.LEFT -> Vector2D( + a.center.x - a.radius * cos(centers.theta), + a.center.y + a.radius * sin(centers.theta) + ) + SIDE.RIGHT -> Vector2D( + a.center.x + a.radius * cos(centers.theta), + a.center.y - a.radius * sin(centers.theta) + ) + } + return Straight( + p1, + Vector2D(p1.x + (centers.end.x - centers.start.x), p1.y + (centers.end.y - centers.start.y)) + ) +} + +internal fun leftInnerTangent(base: Circle, direction: Circle) = innerTangent(base, direction, SIDE.LEFT) +internal fun rightInnerTangent(base: Circle, direction: Circle) = innerTangent(base, direction, SIDE.RIGHT) +private fun innerTangent(base: Circle, direction: Circle, side: SIDE): Straight? { + val centers = Straight(base.center, direction.center) + if (centers.length < base.radius * 2) return null + val angle = theta( + when (side) { + SIDE.LEFT -> centers.theta + acos(base.radius * 2 / centers.length) + SIDE.RIGHT -> centers.theta - acos(base.radius * 2 / centers.length) + } + ) + val dX = base.radius * sin(angle) + val dY = base.radius * cos(angle) + val p1 = Vector2D(base.center.x + dX, base.center.y + dY) + val p2 = Vector2D(direction.center.x - dX, direction.center.y - dY) + return Straight(p1, p2) +} + +internal fun theta(theta: Double) = (theta + (2 * PI)) % (2 * PI) 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 025aab2b7..a5288e40d 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 @@ -29,7 +29,7 @@ class DubinsTests { val start = Pose2D.of(straight.end, straight.theta) val end = Pose2D.of(lineP1.start, lineP1.theta) val radius = 2.0 - val dubins = DubinsPathFactory(start, end, radius) + val dubins = DubinsPath.all(start, end, radius) val absoluteDistance = start.distanceTo(end) println("Absolute distance: $absoluteDistance") @@ -43,7 +43,7 @@ class DubinsTests { ) expectedLengths.forEach { - val path = dubins[it.key] + val path = dubins.find { p -> p.type === it.key } assertNotNull(path, "Path ${it.key} not found") println("${it.key}: ${path.length}") assertTrue(it.value.equalFloat(path.length)) -- 2.34.1 From 86fce7ec68d10dda664ddd936652eacd387c83b8 Mon Sep 17 00:00:00 2001 From: Erik Schouten Date: Sun, 17 Jul 2022 15:47:05 +0200 Subject: [PATCH 153/275] Arc contains circle, circle direction is computed from poses, factory function can create Arc based on Vector points and provided direction --- .../kmath/trajectory/dubins/DubinsPath.kt | 28 ++++---- .../kscience/kmath/trajectory/segments/Arc.kt | 64 +++++++++++-------- .../kmath/trajectory/dubins/DubinsTests.kt | 12 ++-- .../kmath/trajectory/segments/ArcTests.kt | 6 +- 4 files changed, 61 insertions(+), 49 deletions(-) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPath.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPath.kt index ad67fa11d..ee4f38662 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPath.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPath.kt @@ -65,9 +65,9 @@ public class DubinsPath( dX = turningRadius * sin(theta) dY = turningRadius * cos(theta) val p2 = Vector2D(e.center.x + dX, e.center.y + dY) - val a1 = Arc(c1.center, start, p1, Arc.Direction.RIGHT) - val a2 = Arc(e.center, p1, p2, Arc.Direction.LEFT) - val a3 = Arc(c2.center, p2, end, Arc.Direction.RIGHT) + val a1 = Arc.of(c1.center, start, p1, Arc.Direction.RIGHT) + val a2 = Arc.of(e.center, p1, p2, Arc.Direction.LEFT) + val a3 = Arc.of(c2.center, p2, end, Arc.Direction.RIGHT) return DubinsPath(a1, a2, a3) } @@ -87,9 +87,9 @@ public class DubinsPath( dX = turningRadius * sin(theta) dY = turningRadius * cos(theta) val p2 = Vector2D(e.center.x + dX, e.center.y + dY) - val a1 = Arc(c1.center, start, p1, Arc.Direction.LEFT) - val a2 = Arc(e.center, p1, p2, Arc.Direction.RIGHT) - val a3 = Arc(c2.center, p2, end, Arc.Direction.LEFT) + val a1 = Arc.of(c1.center, start, p1, Arc.Direction.LEFT) + val a2 = Arc.of(e.center, p1, p2, Arc.Direction.RIGHT) + val a3 = Arc.of(c2.center, p2, end, Arc.Direction.LEFT) return DubinsPath(a1, a2, a3) } @@ -97,8 +97,8 @@ public class DubinsPath( val c1 = start.getRightCircle(turningRadius) val c2 = end.getRightCircle(turningRadius) val s = leftOuterTangent(c1, c2) - val a1 = Arc(c1.center, start, s.start, Arc.Direction.RIGHT) - val a3 = Arc(c2.center, s.end, end, Arc.Direction.RIGHT) + val a1 = Arc.of(c1.center, start, s.start, Arc.Direction.RIGHT) + val a3 = Arc.of(c2.center, s.end, end, Arc.Direction.RIGHT) return DubinsPath(a1, s, a3) } @@ -106,8 +106,8 @@ public class DubinsPath( val c1 = start.getLeftCircle(turningRadius) val c2 = end.getLeftCircle(turningRadius) val s = rightOuterTangent(c1, c2) - val a1 = Arc(c1.center, start, s.start, Arc.Direction.LEFT) - val a3 = Arc(c2.center, s.end, end, Arc.Direction.LEFT) + val a1 = Arc.of(c1.center, start, s.start, Arc.Direction.LEFT) + val a3 = Arc.of(c2.center, s.end, end, Arc.Direction.LEFT) return DubinsPath(a1, s, a3) } @@ -117,8 +117,8 @@ public class DubinsPath( val s = rightInnerTangent(c1, c2) if (c1.center.distanceTo(c2.center) < turningRadius * 2 || s == null) return null - val a1 = Arc(c1.center, start, s.start, Arc.Direction.RIGHT) - val a3 = Arc(c2.center, s.end, end, Arc.Direction.LEFT) + val a1 = Arc.of(c1.center, start, s.start, Arc.Direction.RIGHT) + val a3 = Arc.of(c2.center, s.end, end, Arc.Direction.LEFT) return DubinsPath(a1, s, a3) } @@ -128,8 +128,8 @@ public class DubinsPath( val s = leftInnerTangent(c1, c2) if (c1.center.distanceTo(c2.center) < turningRadius * 2 || s == null) return null - val a1 = Arc(c1.center, start, s.start, Arc.Direction.LEFT) - val a3 = Arc(c2.center, s.end, end, Arc.Direction.RIGHT) + val a1 = Arc.of(c1.center, start, s.start, Arc.Direction.LEFT) + val a3 = Arc.of(c2.center, s.end, end, Arc.Direction.RIGHT) return DubinsPath(a1, s, a3) } } diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt index fe101f359..966e1e4e2 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt @@ -1,44 +1,56 @@ package space.kscience.kmath.trajectory.segments -import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo import space.kscience.kmath.geometry.Vector2D import space.kscience.kmath.trajectory.dubins.theta import space.kscience.kmath.trajectory.segments.components.Circle import space.kscience.kmath.trajectory.segments.components.Pose2D import kotlin.math.PI -public class Arc( - center: Vector2D, - a: Vector2D, - b: Vector2D, - internal val direction: Direction -) : Circle(center, center.distanceTo(a)), Segment { +public data class Arc( + public val circle: Circle, + public val start: Pose2D, + public val end: Pose2D +) : Segment { - private val s1 = Straight(center, a) - private val s2 = Straight(center, b) + internal companion object { + fun of(center: Vector2D, start: Vector2D, end: Vector2D, direction: Direction): Arc { + val s1 = Straight(center, start) + val s2 = Straight(center, end) + val pose1 = calculatePose(start, s1.theta, direction) + val pose2 = calculatePose(end, s2.theta, direction) + return Arc(Circle(center, s1.length), pose1, pose2) + } - internal val pose1 = calculatePose(a, s1.theta) - internal val pose2 = calculatePose(b, s2.theta) - private val angle = calculateAngle() - override val length: Double = calculateLength() + private fun calculatePose(vector: Vector2D, theta: Double, direction: Direction): Pose2D = + Pose2D.of( + vector, + when (direction) { + Direction.LEFT -> theta(theta - PI / 2) + Direction.RIGHT -> theta(theta + PI / 2) + } + ) + } - public enum class Direction { + internal enum class Direction { LEFT, RIGHT } - private fun calculateAngle() = theta(if (direction == Direction.LEFT) s1.theta - s2.theta else s2.theta - s1.theta) - - private fun calculateLength(): Double { + override val length: Double get() { + val angle: Double = theta(if (direction == Direction.LEFT) start.theta - end.theta else end.theta - start.theta) val proportion = angle / (2 * PI) - return circumference * proportion + return circle.circumference * proportion + } + + internal val direction: Direction = if (start.y < circle.center.y) { + if (start.theta > PI) Direction.RIGHT else Direction.LEFT + } else if (start.y > circle.center.y) { + if (start.theta < PI) Direction.RIGHT else Direction.LEFT + } else { + if (start.theta == 0.0) { + if (start.x < circle.center.x) Direction.RIGHT else Direction.LEFT + } else { + if (start.x > circle.center.x) Direction.RIGHT else Direction.LEFT + } } - private fun calculatePose(vector: Vector2D, theta: Double): Pose2D = - Pose2D.of( - vector, - when (direction) { - Direction.LEFT -> theta(theta - PI / 2) - Direction.RIGHT -> 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 a5288e40d..47e6ac2ef 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 @@ -48,18 +48,18 @@ class DubinsTests { println("${it.key}: ${path.length}") assertTrue(it.value.equalFloat(path.length)) - assertTrue(start.equalsFloat(path.a.pose1)) - assertTrue(end.equalsFloat(path.c.pose2)) + assertTrue(start.equalsFloat(path.a.start)) + assertTrue(end.equalsFloat(path.c.end)) // Not working, theta double precision inaccuracy if (path.b is Arc) { val b = path.b as Arc - assertTrue(path.a.pose2.equalsFloat(b.pose1)) - assertTrue(path.c.pose1.equalsFloat(b.pose2)) + assertTrue(path.a.end.equalsFloat(b.start)) + assertTrue(path.c.start.equalsFloat(b.end)) } else if (path.b is Straight) { val b = path.b as Straight - assertTrue(path.a.pose2.equalsFloat(Pose2D.of(b.start, b.theta))) - assertTrue(path.c.pose1.equalsFloat(Pose2D.of(b.end, b.theta))) + assertTrue(path.a.end.equalsFloat(Pose2D.of(b.start, b.theta))) + assertTrue(path.c.start.equalsFloat(Pose2D.of(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 a59643c0c..5b4ae6d7a 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 @@ -11,9 +11,9 @@ class ArcTests { @Test fun arcTest() { val circle = Circle(Vector2D(0.0, 0.0), 2.0) - val arc = Arc(circle.center, Vector2D(-2.0, 0.0), Vector2D(0.0, 2.0), Arc.Direction.RIGHT) + val arc = Arc.of(circle.center, Vector2D(-2.0, 0.0), Vector2D(0.0, 2.0), Arc.Direction.RIGHT) assertEquals(circle.circumference / 4, arc.length, 1.0) - assertEquals(0.0, arc.pose1.theta.radiansToDegrees()) - assertEquals(90.0, arc.pose2.theta.radiansToDegrees()) + assertEquals(0.0, arc.start.theta.radiansToDegrees()) + assertEquals(90.0, arc.end.theta.radiansToDegrees()) } } -- 2.34.1 From 429eefa3f7750c4d8e6dfccabb1206c77988ec38 Mon Sep 17 00:00:00 2001 From: Erik Schouten Date: Sun, 17 Jul 2022 15:48:08 +0200 Subject: [PATCH 154/275] Arc direction as computed property --- .../kscience/kmath/trajectory/segments/Arc.kt | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt index 966e1e4e2..1c02dd952 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt @@ -35,22 +35,25 @@ public data class Arc( LEFT, RIGHT } - override val length: Double get() { - val angle: Double = theta(if (direction == Direction.LEFT) start.theta - end.theta else end.theta - start.theta) - val proportion = angle / (2 * PI) - return circle.circumference * proportion - } - - internal val direction: Direction = if (start.y < circle.center.y) { - if (start.theta > PI) Direction.RIGHT else Direction.LEFT - } else if (start.y > circle.center.y) { - if (start.theta < PI) Direction.RIGHT else Direction.LEFT - } else { - if (start.theta == 0.0) { - if (start.x < circle.center.x) Direction.RIGHT else Direction.LEFT - } else { - if (start.x > circle.center.x) Direction.RIGHT else Direction.LEFT + override val length: Double + get() { + val angle: Double = + theta(if (direction == Direction.LEFT) start.theta - end.theta else end.theta - start.theta) + val proportion = angle / (2 * PI) + return circle.circumference * proportion + } + + internal val direction: Direction + get() = if (start.y < circle.center.y) { + if (start.theta > PI) Direction.RIGHT else Direction.LEFT + } else if (start.y > circle.center.y) { + if (start.theta < PI) Direction.RIGHT else Direction.LEFT + } else { + if (start.theta == 0.0) { + if (start.x < circle.center.x) Direction.RIGHT else Direction.LEFT + } else { + if (start.x > circle.center.x) Direction.RIGHT else Direction.LEFT + } } - } } -- 2.34.1 From f2cbbeba2017af8dd54795e9c4b0ef82682b7715 Mon Sep 17 00:00:00 2001 From: Erik Schouten Date: Sun, 17 Jul 2022 15:56:24 +0200 Subject: [PATCH 155/275] Author details --- docs/templates/README-TEMPLATE.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/templates/README-TEMPLATE.md b/docs/templates/README-TEMPLATE.md index 4ffa9e75f..c466324b8 100644 --- a/docs/templates/README-TEMPLATE.md +++ b/docs/templates/README-TEMPLATE.md @@ -103,3 +103,10 @@ The project requires a lot of additional work. The most important thing we need required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues marked with [waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero) label. + +## Author +Erik Schouten + +Github: ESchouten + +Email: erik-schouten@hotmail.nl -- 2.34.1 From 9d4df5d8e03a1aadb85109e3fabb2d25694b1695 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Wed, 20 Jul 2022 08:22:41 +0300 Subject: [PATCH 156/275] Add and regenerate READMEs. Fix files' directory. --- README.md | 31 +++++++++++- kmath-ast/README.md | 6 +-- kmath-commons/README.md | 6 +-- kmath-complex/README.md | 10 ++-- kmath-core/README.md | 6 +-- kmath-coroutines/README.md | 6 +-- kmath-dimensions/README.md | 6 +-- kmath-ejml/README.md | 6 +-- kmath-for-real/README.md | 6 +-- kmath-functions/README.md | 6 +-- kmath-geometry/README.md | 6 +-- kmath-histograms/README.md | 6 +-- kmath-jafama/README.md | 6 +-- kmath-jupyter/README.md | 6 +-- kmath-kotlingrad/README.md | 6 +-- kmath-memory/README.md | 6 +-- kmath-multik/README.md | 6 +-- kmath-nd4j/README.md | 6 +-- kmath-optimization/README.md | 6 +-- kmath-polynomial/README.md | 50 +++++++++++++++++++ kmath-polynomial/build.gradle.kts | 43 +++++++++++++++- .../kmath/functions}/LabeledPolynomial.kt | 0 .../functions}/LabeledRationalFunction.kt | 0 .../kmath/functions}/ListPolynomial.kt | 0 .../kmath/functions}/ListRationalFunction.kt | 0 .../kmath/functions}/NumberedPolynomial.kt | 0 .../functions}/NumberedRationalFunction.kt | 0 .../kscience/kmath/functions}/Polynomial.kt | 0 .../kmath/functions}/RationalFunction.kt | 0 .../kmath/functions}/algebraicStub.kt | 0 .../kmath/functions}/collectionUtils.kt | 0 .../kmath/functions}/labeledConstructors.kt | 0 .../kscience/kmath/functions}/labeledUtil.kt | 0 .../kmath/functions}/listConstructors.kt | 0 .../kscience/kmath/functions}/listUtil.kt | 0 .../kscience/kmath/functions}/misc.kt | 0 .../kmath/functions}/numberedConstructors.kt | 0 .../kscience/kmath/functions}/numberedUtil.kt | 0 kmath-stat/README.md | 6 +-- kmath-symja/README.md | 6 +-- kmath-tensorflow/README.md | 6 +-- kmath-tensors/README.md | 6 +-- kmath-viktor/README.md | 6 +-- 43 files changed, 192 insertions(+), 74 deletions(-) create mode 100644 kmath-polynomial/README.md rename kmath-polynomial/src/commonMain/kotlin/{space.kscience.kmath.functions => space/kscience/kmath/functions}/LabeledPolynomial.kt (100%) rename kmath-polynomial/src/commonMain/kotlin/{space.kscience.kmath.functions => space/kscience/kmath/functions}/LabeledRationalFunction.kt (100%) rename kmath-polynomial/src/commonMain/kotlin/{space.kscience.kmath.functions => space/kscience/kmath/functions}/ListPolynomial.kt (100%) rename kmath-polynomial/src/commonMain/kotlin/{space.kscience.kmath.functions => space/kscience/kmath/functions}/ListRationalFunction.kt (100%) rename kmath-polynomial/src/commonMain/kotlin/{space.kscience.kmath.functions => space/kscience/kmath/functions}/NumberedPolynomial.kt (100%) rename kmath-polynomial/src/commonMain/kotlin/{space.kscience.kmath.functions => space/kscience/kmath/functions}/NumberedRationalFunction.kt (100%) rename kmath-polynomial/src/commonMain/kotlin/{space.kscience.kmath.functions => space/kscience/kmath/functions}/Polynomial.kt (100%) rename kmath-polynomial/src/commonMain/kotlin/{space.kscience.kmath.functions => space/kscience/kmath/functions}/RationalFunction.kt (100%) rename kmath-polynomial/src/commonMain/kotlin/{space.kscience.kmath.functions => space/kscience/kmath/functions}/algebraicStub.kt (100%) rename kmath-polynomial/src/commonMain/kotlin/{space.kscience.kmath.functions => space/kscience/kmath/functions}/collectionUtils.kt (100%) rename kmath-polynomial/src/commonMain/kotlin/{space.kscience.kmath.functions => space/kscience/kmath/functions}/labeledConstructors.kt (100%) rename kmath-polynomial/src/commonMain/kotlin/{space.kscience.kmath.functions => space/kscience/kmath/functions}/labeledUtil.kt (100%) rename kmath-polynomial/src/commonMain/kotlin/{space.kscience.kmath.functions => space/kscience/kmath/functions}/listConstructors.kt (100%) rename kmath-polynomial/src/commonMain/kotlin/{space.kscience.kmath.functions => space/kscience/kmath/functions}/listUtil.kt (100%) rename kmath-polynomial/src/commonMain/kotlin/{space.kscience.kmath.functions => space/kscience/kmath/functions}/misc.kt (100%) rename kmath-polynomial/src/commonMain/kotlin/{space.kscience.kmath.functions => space/kscience/kmath/functions}/numberedConstructors.kt (100%) rename kmath-polynomial/src/commonMain/kotlin/{space.kscience.kmath.functions => space/kscience/kmath/functions}/numberedUtil.kt (100%) diff --git a/README.md b/README.md index 8353d341b..39cbf19c9 100644 --- a/README.md +++ b/README.md @@ -86,8 +86,8 @@ module definitions below. The module stability could have the following levels: > **Maturity**: PROTOTYPE > > **Features:** -> - [complex](kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt) : Complex Numbers -> - [quaternion](kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt) : Quaternions +> - [complex](kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt) : Complex numbers operations +> - [quaternion](kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt) : Quaternions and their composition ### [kmath-core](kmath-core) @@ -214,6 +214,28 @@ One can still use generic algebras though. > > **Maturity**: EXPERIMENTAL +### [kmath-polynomial](kmath-polynomial) +> +> +> **Maturity**: PROTOTYPE +> +> **Features:** +> - [polynomial abstraction](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt) : Abstraction for polynomial spaces. +> - [rational function abstraction](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt) : Abstraction for rational functions spaces. +> - ["list" polynomials](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt) : List implementation of univariate polynomials. +> - ["list" rational functions](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt) : List implementation of univariate rational functions. +> - ["list" polynomials and rational functions constructors](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt) : Constructors for list polynomials and rational functions. +> - ["list" polynomials and rational functions utilities](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt) : Utilities for list polynomials and rational functions. +> - ["numbered" polynomials](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt) : Numbered implementation of multivariate polynomials. +> - ["numbered" rational functions](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt) : Numbered implementation of multivariate rational functions. +> - ["numbered" polynomials and rational functions constructors](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt) : Constructors for numbered polynomials and rational functions. +> - ["numbered" polynomials and rational functions utilities](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt) : Utilities for numbered polynomials and rational functions. +> - ["labeled" polynomials](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt) : Labeled implementation of multivariate polynomials. +> - ["labeled" rational functions](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt) : Labeled implementation of multivariate rational functions. +> - ["labeled" polynomials and rational functions constructors](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt) : Constructors for labeled polynomials and rational functions. +> - ["labeled" polynomials and rational functions utilities](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt) : Utilities for labeled polynomials and rational functions. + + ### [kmath-stat](kmath-stat) > > @@ -245,6 +267,11 @@ One can still use generic algebras though. > > **Maturity**: DEVELOPMENT +### [test-utils](test-utils) +> +> +> **Maturity**: EXPERIMENTAL + ## Multi-platform support diff --git a/kmath-ast/README.md b/kmath-ast/README.md index 553c60bb3..c6da64982 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -10,7 +10,7 @@ Extensions to MST API: transformations, dynamic compilation and visualization. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ast:0.3.0' + implementation 'space.kscience:kmath-ast:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -31,7 +31,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ast:0.3.0") + implementation("space.kscience:kmath-ast:0.3.1-dev-1") } ``` diff --git a/kmath-commons/README.md b/kmath-commons/README.md index 7195e6fb1..89f1f6c9f 100644 --- a/kmath-commons/README.md +++ b/kmath-commons/README.md @@ -6,7 +6,7 @@ Commons math binding for kmath ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-commons:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-commons:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-commons:0.3.0' + implementation 'space.kscience:kmath-commons:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-commons:0.3.0") + implementation("space.kscience:kmath-commons:0.3.1-dev-1") } ``` diff --git a/kmath-complex/README.md b/kmath-complex/README.md index 4646c6a80..f00952065 100644 --- a/kmath-complex/README.md +++ b/kmath-complex/README.md @@ -2,13 +2,13 @@ Complex and hypercomplex number systems in KMath. - - [complex](src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt) : Complex Numbers - - [quaternion](src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt) : Quaternions + - [complex](src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt) : Complex numbers operations + - [quaternion](src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt) : Quaternions and their composition ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -18,7 +18,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-complex:0.3.0' + implementation 'space.kscience:kmath-complex:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -29,6 +29,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-complex:0.3.0") + implementation("space.kscience:kmath-complex:0.3.1-dev-1") } ``` diff --git a/kmath-core/README.md b/kmath-core/README.md index 4fddd327c..e84ca38d7 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -15,7 +15,7 @@ performance calculations to code generation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-core:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -25,7 +25,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-core:0.3.0' + implementation 'space.kscience:kmath-core:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -36,6 +36,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-core:0.3.0") + implementation("space.kscience:kmath-core:0.3.1-dev-1") } ``` diff --git a/kmath-coroutines/README.md b/kmath-coroutines/README.md index d0fef6e0f..337d8e037 100644 --- a/kmath-coroutines/README.md +++ b/kmath-coroutines/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-coroutines:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-coroutines:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-coroutines:0.3.0' + implementation 'space.kscience:kmath-coroutines:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-coroutines:0.3.0") + implementation("space.kscience:kmath-coroutines:0.3.1-dev-1") } ``` diff --git a/kmath-dimensions/README.md b/kmath-dimensions/README.md index 650bcafde..12aa2a7fa 100644 --- a/kmath-dimensions/README.md +++ b/kmath-dimensions/README.md @@ -6,7 +6,7 @@ A proof of concept module for adding type-safe dimensions to structures ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-dimensions:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-dimensions:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-dimensions:0.3.0' + implementation 'space.kscience:kmath-dimensions:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-dimensions:0.3.0") + implementation("space.kscience:kmath-dimensions:0.3.1-dev-1") } ``` diff --git a/kmath-ejml/README.md b/kmath-ejml/README.md index eaa90120f..2d6c661e4 100644 --- a/kmath-ejml/README.md +++ b/kmath-ejml/README.md @@ -9,7 +9,7 @@ EJML based linear algebra implementation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ejml:0.3.0' + implementation 'space.kscience:kmath-ejml:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ejml:0.3.0") + implementation("space.kscience:kmath-ejml:0.3.1-dev-1") } ``` diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md index 9e8f95a16..5a8376976 100644 --- a/kmath-for-real/README.md +++ b/kmath-for-real/README.md @@ -9,7 +9,7 @@ Specialization of KMath APIs for Double numbers. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-for-real:0.3.0' + implementation 'space.kscience:kmath-for-real:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-for-real:0.3.0") + implementation("space.kscience:kmath-for-real:0.3.1-dev-1") } ``` diff --git a/kmath-functions/README.md b/kmath-functions/README.md index 3f44bd3f9..1292424b5 100644 --- a/kmath-functions/README.md +++ b/kmath-functions/README.md @@ -11,7 +11,7 @@ Functions and interpolations. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -21,7 +21,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-functions:0.3.0' + implementation 'space.kscience:kmath-functions:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -32,6 +32,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-functions:0.3.0") + implementation("space.kscience:kmath-functions:0.3.1-dev-1") } ``` diff --git a/kmath-geometry/README.md b/kmath-geometry/README.md index 6602f5510..72d275697 100644 --- a/kmath-geometry/README.md +++ b/kmath-geometry/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-geometry:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-geometry:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-geometry:0.3.0' + implementation 'space.kscience:kmath-geometry:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-geometry:0.3.0") + implementation("space.kscience:kmath-geometry:0.3.1-dev-1") } ``` diff --git a/kmath-histograms/README.md b/kmath-histograms/README.md index 27f1b43ec..5fd91ee0c 100644 --- a/kmath-histograms/README.md +++ b/kmath-histograms/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-histograms:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-histograms:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-histograms:0.3.0' + implementation 'space.kscience:kmath-histograms:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-histograms:0.3.0") + implementation("space.kscience:kmath-histograms:0.3.1-dev-1") } ``` diff --git a/kmath-jafama/README.md b/kmath-jafama/README.md index fe6afb835..c008c76ca 100644 --- a/kmath-jafama/README.md +++ b/kmath-jafama/README.md @@ -7,7 +7,7 @@ Integration with [Jafama](https://github.com/jeffhain/jafama). ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-jafama:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-jafama:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -17,7 +17,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-jafama:0.3.0' + implementation 'space.kscience:kmath-jafama:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -28,7 +28,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-jafama:0.3.0") + implementation("space.kscience:kmath-jafama:0.3.1-dev-1") } ``` diff --git a/kmath-jupyter/README.md b/kmath-jupyter/README.md index db58ad840..3c9832625 100644 --- a/kmath-jupyter/README.md +++ b/kmath-jupyter/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-jupyter:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-jupyter:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-jupyter:0.3.0' + implementation 'space.kscience:kmath-jupyter:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-jupyter:0.3.0") + implementation("space.kscience:kmath-jupyter:0.3.1-dev-1") } ``` diff --git a/kmath-kotlingrad/README.md b/kmath-kotlingrad/README.md index 52e8b3116..457652aaf 100644 --- a/kmath-kotlingrad/README.md +++ b/kmath-kotlingrad/README.md @@ -8,7 +8,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-kotlingrad:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-kotlingrad:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -18,7 +18,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-kotlingrad:0.3.0' + implementation 'space.kscience:kmath-kotlingrad:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -29,6 +29,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-kotlingrad:0.3.0") + implementation("space.kscience:kmath-kotlingrad:0.3.1-dev-1") } ``` diff --git a/kmath-memory/README.md b/kmath-memory/README.md index 9f4520bd8..536d7f145 100644 --- a/kmath-memory/README.md +++ b/kmath-memory/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-memory:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-memory:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-memory:0.3.0' + implementation 'space.kscience:kmath-memory:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-memory:0.3.0") + implementation("space.kscience:kmath-memory:0.3.1-dev-1") } ``` diff --git a/kmath-multik/README.md b/kmath-multik/README.md index edfce6f79..0f5b65b4c 100644 --- a/kmath-multik/README.md +++ b/kmath-multik/README.md @@ -6,7 +6,7 @@ JetBrains Multik connector ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-multik:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-multik:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-multik:0.3.0' + implementation 'space.kscience:kmath-multik:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-multik:0.3.0") + implementation("space.kscience:kmath-multik:0.3.1-dev-1") } ``` diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index 0bcae138e..bb065a300 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -9,7 +9,7 @@ ND4J based implementations of KMath abstractions. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-nd4j:0.3.0' + implementation 'space.kscience:kmath-nd4j:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -30,7 +30,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-nd4j:0.3.0") + implementation("space.kscience:kmath-nd4j:0.3.1-dev-1") } ``` diff --git a/kmath-optimization/README.md b/kmath-optimization/README.md index 63e0f43e3..d7441ebd1 100644 --- a/kmath-optimization/README.md +++ b/kmath-optimization/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-optimization:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-optimization:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-optimization:0.3.0' + implementation 'space.kscience:kmath-optimization:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-optimization:0.3.0") + implementation("space.kscience:kmath-optimization:0.3.1-dev-1") } ``` diff --git a/kmath-polynomial/README.md b/kmath-polynomial/README.md new file mode 100644 index 000000000..640ea8876 --- /dev/null +++ b/kmath-polynomial/README.md @@ -0,0 +1,50 @@ +# Module kmath-polynomial + +Polynomial extra utilities and rational functions + +## 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 index 85b87fb34..dd0d9e77d 100644 --- a/kmath-polynomial/build.gradle.kts +++ b/kmath-polynomial/build.gradle.kts @@ -22,5 +22,46 @@ readme { maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) -// feature("TODO") { "TODO" } + 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 similarity index 100% rename from kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/LabeledPolynomial.kt rename to kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt 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 similarity index 100% rename from kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/LabeledRationalFunction.kt rename to kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt 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 similarity index 100% rename from kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/ListPolynomial.kt rename to kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt 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 similarity index 100% rename from kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/ListRationalFunction.kt rename to kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt 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 similarity index 100% rename from kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/NumberedPolynomial.kt rename to kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt 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 similarity index 100% rename from kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/NumberedRationalFunction.kt rename to kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt 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 similarity index 100% rename from kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/Polynomial.kt rename to kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt 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 similarity index 100% rename from kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/RationalFunction.kt rename to kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt 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 similarity index 100% rename from kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/algebraicStub.kt rename to kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt 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 similarity index 100% rename from kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/collectionUtils.kt rename to kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/collectionUtils.kt 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 similarity index 100% rename from kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/labeledConstructors.kt rename to kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt 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 similarity index 100% rename from kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/labeledUtil.kt rename to kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt 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 similarity index 100% rename from kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/listConstructors.kt rename to kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt 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 similarity index 100% rename from kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/listUtil.kt rename to kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt 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 similarity index 100% rename from kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/misc.kt rename to kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt 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 similarity index 100% rename from kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/numberedConstructors.kt rename to kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt 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 similarity index 100% rename from kmath-polynomial/src/commonMain/kotlin/space.kscience.kmath.functions/numberedUtil.kt rename to kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt diff --git a/kmath-stat/README.md b/kmath-stat/README.md index 80c6e0fcd..7ed20fcf4 100644 --- a/kmath-stat/README.md +++ b/kmath-stat/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-stat:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-stat:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-stat:0.3.0' + implementation 'space.kscience:kmath-stat:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-stat:0.3.0") + implementation("space.kscience:kmath-stat:0.3.1-dev-1") } ``` diff --git a/kmath-symja/README.md b/kmath-symja/README.md index ea2d5d68f..a96b0e835 100644 --- a/kmath-symja/README.md +++ b/kmath-symja/README.md @@ -6,7 +6,7 @@ Symja integration module ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-symja:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-symja:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-symja:0.3.0' + implementation 'space.kscience:kmath-symja:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-symja:0.3.0") + implementation("space.kscience:kmath-symja:0.3.1-dev-1") } ``` diff --git a/kmath-tensorflow/README.md b/kmath-tensorflow/README.md index 7852c07be..83f2eb315 100644 --- a/kmath-tensorflow/README.md +++ b/kmath-tensorflow/README.md @@ -6,7 +6,7 @@ Google tensorflow connector ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-tensorflow:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-tensorflow:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-tensorflow:0.3.0' + implementation 'space.kscience:kmath-tensorflow:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-tensorflow:0.3.0") + implementation("space.kscience:kmath-tensorflow:0.3.1-dev-1") } ``` diff --git a/kmath-tensors/README.md b/kmath-tensors/README.md index 44ee47675..4208cd83d 100644 --- a/kmath-tensors/README.md +++ b/kmath-tensors/README.md @@ -9,7 +9,7 @@ Common linear algebra operations on tensors. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-tensors:0.3.0' + implementation 'space.kscience:kmath-tensors:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-tensors:0.3.0") + implementation("space.kscience:kmath-tensors:0.3.1-dev-1") } ``` diff --git a/kmath-viktor/README.md b/kmath-viktor/README.md index 5d7c2dea1..abff20427 100644 --- a/kmath-viktor/README.md +++ b/kmath-viktor/README.md @@ -6,7 +6,7 @@ Binding for https://github.com/JetBrains-Research/viktor ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-viktor:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-viktor:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-viktor:0.3.0' + implementation 'space.kscience:kmath-viktor:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-viktor:0.3.0") + implementation("space.kscience:kmath-viktor:0.3.1-dev-1") } ``` -- 2.34.1 From 163a7c717a922b8f670475ad489184dd28716c11 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Wed, 20 Jul 2022 08:28:47 +0300 Subject: [PATCH 157/275] Fix description. --- kmath-polynomial/README.md | 2 +- kmath-polynomial/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kmath-polynomial/README.md b/kmath-polynomial/README.md index 640ea8876..a5078a7e0 100644 --- a/kmath-polynomial/README.md +++ b/kmath-polynomial/README.md @@ -1,6 +1,6 @@ # Module kmath-polynomial -Polynomial extra utilities and rational functions +Polynomials, rational functions, and utilities ## Features diff --git a/kmath-polynomial/build.gradle.kts b/kmath-polynomial/build.gradle.kts index dd0d9e77d..9c5083d2d 100644 --- a/kmath-polynomial/build.gradle.kts +++ b/kmath-polynomial/build.gradle.kts @@ -4,7 +4,7 @@ plugins { id("ru.mipt.npm.gradle.native") } -description = "Polynomial extra utilities and rational functions" +description = "Polynomials, rational functions, and utilities" kotlin.sourceSets { commonMain { -- 2.34.1 From fe4eb96daed13a30d9c7f328fa49d2daefe9a2f5 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Wed, 20 Jul 2022 19:09:20 +0300 Subject: [PATCH 158/275] Add docs. --- .../kmath/functions/collectionUtils.kt | 451 ++++++++++++++++-- 1 file changed, 412 insertions(+), 39 deletions(-) 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 index ee32aa9a7..0d2ea3653 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/collectionUtils.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/collectionUtils.kt @@ -9,7 +9,13 @@ import kotlin.contracts.InvocationKind.* import kotlin.contracts.contract -// TODO: Docs +/** + * 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) @@ -17,7 +23,15 @@ internal inline fun Map.computeOn(key: K, compute: (V?) -> R) return compute(get(key)) } -// TODO: Docs +/** + * 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) @@ -27,7 +41,15 @@ internal inline fun Map.computeOnOrElse(key: K, defaultResult: ( return (if (key !in this) defaultResult() else compute(get(key) as V)) } -// TODO: Docs +/** + * 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) @@ -35,7 +57,15 @@ internal inline fun Map.computeOnOrElse(key: K, defaultResult: R return computeOnOrElse(key, { defaultResult }, compute) } -// TODO: Docs +/** + * 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) @@ -374,8 +404,20 @@ internal inline fun > Map.copyMapToBy(des 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) }) -// TODO: Docs -internal fun > mergeTo(map1: Map, map2: Map, destination: D): D { +/** + * 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) } @@ -385,7 +427,20 @@ internal fun > mergeTo(map1: Map, map2: Map< return destination } -// TODO: Docs +/** + * 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) @@ -400,27 +455,82 @@ internal inline fun > mergeToBy(map1: Ma return destination } -// TODO: Docs +/** + * 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) } -// TODO: Docs +/** + * 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) } -// TODO: Docs -internal inline fun mergeBy(map1: Map, map2: Map, transform: (key: K, value1: V1, value2: V2) -> W): Map { +/** + * 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, transform) + return mergeToBy(map1, map2, result, resolve) } -// TODO: Docs -internal inline fun mergeBy(map1: Map, map2: Map, transform: (value1: V1, value2: V2) -> W): Map = - mergeBy(map1, map2) { _, value1, value2 -> transform(value1, value2) } +/** + * 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) } -// TODO: Docs +/** + * 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) @@ -429,7 +539,20 @@ internal inline fun > Iterable.associateTo(dest return destination } -// TODO: Docs +/** + * 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) @@ -439,7 +562,19 @@ internal inline fun > Iterable.associateByTo(de return destination } -// TODO: Docs +/** + * 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) @@ -448,86 +583,324 @@ internal inline fun > Iterable.associateByTo(desti return destination } -// TODO: Docs +/** + * 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) } -// TODO: Docs +/** + * 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) } -// TODO: Docs +/** + * 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) } -// TODO: Docs +/** + * 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) -// TODO: Docs +/** + * 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) -// TODO: Docs +/** + * 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) -// TODO: Docs +/** + * 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) -// TODO: Docs +/** + * 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) -// TODO: Docs +/** + * 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) -// TODO: Docs +/** + * 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) -// TODO: Docs +/** + * 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) -// TODO: Docs +/** + * 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) -// TODO: Docs +/** + * 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) -// TODO: Docs +/** + * 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) -// TODO: Docs +/** + * 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) -// TODO: Docs +/** + * 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) -// TODO: Docs +/** + * 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) -// TODO: Docs +/** + * 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) -// TODO: Docs +/** + * 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) -// TODO: Docs +/** + * 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) -// TODO: Docs +/** + * 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 -- 2.34.1 From e1b8fcdbbf78d13a04aa0602e2f341d420f8b103 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Wed, 20 Jul 2022 19:10:35 +0300 Subject: [PATCH 159/275] Two consecutive dots... --- .../kotlin/space/kscience/kmath/functions/collectionUtils.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 0d2ea3653..c9146a493 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/collectionUtils.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/collectionUtils.kt @@ -894,7 +894,7 @@ internal inline fun Map.mapKeys(transform: (Map.Entry) /** * 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.. + * map and the values of this map and resolving conflicts with [resolve] function. * * All pairs are added and resolved in order of iteration. * -- 2.34.1 From 0c6ad35c13ecf6bff31170092685e71ce016f1b5 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sat, 23 Jul 2022 10:24:52 +0300 Subject: [PATCH 160/275] Simplify the version catalog usage. --- kmath-functions/build.gradle.kts | 2 +- kmath-polynomial/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kmath-functions/build.gradle.kts b/kmath-functions/build.gradle.kts index eec17e82b..337875ba4 100644 --- a/kmath-functions/build.gradle.kts +++ b/kmath-functions/build.gradle.kts @@ -15,7 +15,7 @@ kotlin.sourceSets { } dependencies { - dokkaPlugin("org.jetbrains.dokka:mathjax-plugin:${versionCatalogs.named("npmlibs").findVersion("dokka").get().requiredVersion}") + dokkaPlugin("org.jetbrains.dokka:mathjax-plugin:${npmlibs.versions.dokka.get()}") } readme { diff --git a/kmath-polynomial/build.gradle.kts b/kmath-polynomial/build.gradle.kts index 9c5083d2d..5e66f83ec 100644 --- a/kmath-polynomial/build.gradle.kts +++ b/kmath-polynomial/build.gradle.kts @@ -15,7 +15,7 @@ kotlin.sourceSets { } dependencies { - dokkaPlugin("org.jetbrains.dokka:mathjax-plugin:${versionCatalogs.named("npmlibs").findVersion("dokka").get().requiredVersion}") + dokkaPlugin("org.jetbrains.dokka:mathjax-plugin:${npmlibs.versions.dokka.get()}") } readme { -- 2.34.1 From 1e8a8cac7efa0d10495aca413ed3c5fa82c6fba1 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 24 Jul 2022 12:01:02 +0300 Subject: [PATCH 161/275] Fix readme --- .github/CODEOWNERS | 3 +++ .space/CODEOWNERS | 0 README.md | 19 ++++++++++++++----- docs/templates/README-TEMPLATE.md | 12 ++---------- kmath-ast/README.md | 6 +++--- kmath-commons/README.md | 6 +++--- kmath-complex/README.md | 10 +++++----- kmath-core/README.md | 6 +++--- kmath-coroutines/README.md | 6 +++--- kmath-dimensions/README.md | 6 +++--- kmath-ejml/README.md | 6 +++--- kmath-for-real/README.md | 6 +++--- kmath-functions/README.md | 6 +++--- kmath-geometry/README.md | 6 +++--- kmath-histograms/README.md | 6 +++--- kmath-jafama/README.md | 6 +++--- kmath-jupyter/README.md | 6 +++--- kmath-kotlingrad/README.md | 6 +++--- kmath-memory/README.md | 6 +++--- kmath-multik/README.md | 6 +++--- kmath-nd4j/README.md | 6 +++--- kmath-optimization/README.md | 6 +++--- kmath-stat/README.md | 6 +++--- kmath-symja/README.md | 6 +++--- kmath-tensorflow/README.md | 6 +++--- kmath-tensors/README.md | 6 +++--- kmath-trajectory/README.md | 12 +++++++----- kmath-trajectory/build.gradle.kts | 2 ++ kmath-trajectory/docs/README-TEMPLATE.md | 13 +++++++++++++ kmath-viktor/README.md | 6 +++--- 30 files changed, 112 insertions(+), 91 deletions(-) create mode 100644 .github/CODEOWNERS create mode 100644 .space/CODEOWNERS create mode 100644 kmath-trajectory/docs/README-TEMPLATE.md diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..7273b6a50 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,3 @@ +@altavir + +/kmath-trajectory @ESchouten \ No newline at end of file diff --git a/.space/CODEOWNERS b/.space/CODEOWNERS new file mode 100644 index 000000000..e69de29bb diff --git a/README.md b/README.md index 8353d341b..63238f320 100644 --- a/README.md +++ b/README.md @@ -86,8 +86,8 @@ module definitions below. The module stability could have the following levels: > **Maturity**: PROTOTYPE > > **Features:** -> - [complex](kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt) : Complex Numbers -> - [quaternion](kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt) : Quaternions +> - [complex](kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt) : Complex numbers operations +> - [quaternion](kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt) : Quaternions and their composition ### [kmath-core](kmath-core) @@ -240,11 +240,21 @@ One can still use generic algebras though. > - [linear algebra operations](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Advanced linear algebra operations like LU decomposition, SVD, etc. +### [kmath-trajectory](kmath-trajectory) +> Path and trajectory optimization +> +> **Maturity**: PROTOTYPE + ### [kmath-viktor](kmath-viktor) > > > **Maturity**: DEVELOPMENT +### [test-utils](test-utils) +> +> +> **Maturity**: EXPERIMENTAL + ## Multi-platform support @@ -261,8 +271,7 @@ performance and flexibility. We expect to focus on creating convenient universal API first and then work on increasing performance for specific cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized -native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be -better than SciPy. +native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be better than SciPy. ## Requirements @@ -294,4 +303,4 @@ Gradle `6.0+` is required for multiplatform artifacts. The project requires a lot of additional work. The most important thing we need is a feedback about what features are required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues marked with -[waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero) label. +[waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero) label. \ No newline at end of file diff --git a/docs/templates/README-TEMPLATE.md b/docs/templates/README-TEMPLATE.md index b8446a76f..1633f3ff1 100644 --- a/docs/templates/README-TEMPLATE.md +++ b/docs/templates/README-TEMPLATE.md @@ -69,8 +69,7 @@ performance and flexibility. We expect to focus on creating convenient universal API first and then work on increasing performance for specific cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized -native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be -better than SciPy. +native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be better than SciPy. ## Requirements @@ -102,11 +101,4 @@ Gradle `6.0+` is required for multiplatform artifacts. The project requires a lot of additional work. The most important thing we need is a feedback about what features are required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues marked with -[waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero) label. - -## Author -Erik Schouten - -Github: ESchouten - -Email: erik-schouten@hotmail.nl +[waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero) label. \ No newline at end of file diff --git a/kmath-ast/README.md b/kmath-ast/README.md index 553c60bb3..c6da64982 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -10,7 +10,7 @@ Extensions to MST API: transformations, dynamic compilation and visualization. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ast:0.3.0' + implementation 'space.kscience:kmath-ast:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -31,7 +31,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ast:0.3.0") + implementation("space.kscience:kmath-ast:0.3.1-dev-1") } ``` diff --git a/kmath-commons/README.md b/kmath-commons/README.md index 7195e6fb1..89f1f6c9f 100644 --- a/kmath-commons/README.md +++ b/kmath-commons/README.md @@ -6,7 +6,7 @@ Commons math binding for kmath ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-commons:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-commons:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-commons:0.3.0' + implementation 'space.kscience:kmath-commons:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-commons:0.3.0") + implementation("space.kscience:kmath-commons:0.3.1-dev-1") } ``` diff --git a/kmath-complex/README.md b/kmath-complex/README.md index 4646c6a80..f00952065 100644 --- a/kmath-complex/README.md +++ b/kmath-complex/README.md @@ -2,13 +2,13 @@ Complex and hypercomplex number systems in KMath. - - [complex](src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt) : Complex Numbers - - [quaternion](src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt) : Quaternions + - [complex](src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt) : Complex numbers operations + - [quaternion](src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt) : Quaternions and their composition ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -18,7 +18,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-complex:0.3.0' + implementation 'space.kscience:kmath-complex:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -29,6 +29,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-complex:0.3.0") + implementation("space.kscience:kmath-complex:0.3.1-dev-1") } ``` diff --git a/kmath-core/README.md b/kmath-core/README.md index 4fddd327c..e84ca38d7 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -15,7 +15,7 @@ performance calculations to code generation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-core:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -25,7 +25,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-core:0.3.0' + implementation 'space.kscience:kmath-core:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -36,6 +36,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-core:0.3.0") + implementation("space.kscience:kmath-core:0.3.1-dev-1") } ``` diff --git a/kmath-coroutines/README.md b/kmath-coroutines/README.md index d0fef6e0f..337d8e037 100644 --- a/kmath-coroutines/README.md +++ b/kmath-coroutines/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-coroutines:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-coroutines:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-coroutines:0.3.0' + implementation 'space.kscience:kmath-coroutines:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-coroutines:0.3.0") + implementation("space.kscience:kmath-coroutines:0.3.1-dev-1") } ``` diff --git a/kmath-dimensions/README.md b/kmath-dimensions/README.md index 650bcafde..12aa2a7fa 100644 --- a/kmath-dimensions/README.md +++ b/kmath-dimensions/README.md @@ -6,7 +6,7 @@ A proof of concept module for adding type-safe dimensions to structures ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-dimensions:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-dimensions:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-dimensions:0.3.0' + implementation 'space.kscience:kmath-dimensions:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-dimensions:0.3.0") + implementation("space.kscience:kmath-dimensions:0.3.1-dev-1") } ``` diff --git a/kmath-ejml/README.md b/kmath-ejml/README.md index eaa90120f..2d6c661e4 100644 --- a/kmath-ejml/README.md +++ b/kmath-ejml/README.md @@ -9,7 +9,7 @@ EJML based linear algebra implementation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ejml:0.3.0' + implementation 'space.kscience:kmath-ejml:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ejml:0.3.0") + implementation("space.kscience:kmath-ejml:0.3.1-dev-1") } ``` diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md index 9e8f95a16..5a8376976 100644 --- a/kmath-for-real/README.md +++ b/kmath-for-real/README.md @@ -9,7 +9,7 @@ Specialization of KMath APIs for Double numbers. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-for-real:0.3.0' + implementation 'space.kscience:kmath-for-real:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-for-real:0.3.0") + implementation("space.kscience:kmath-for-real:0.3.1-dev-1") } ``` diff --git a/kmath-functions/README.md b/kmath-functions/README.md index 3f44bd3f9..1292424b5 100644 --- a/kmath-functions/README.md +++ b/kmath-functions/README.md @@ -11,7 +11,7 @@ Functions and interpolations. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -21,7 +21,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-functions:0.3.0' + implementation 'space.kscience:kmath-functions:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -32,6 +32,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-functions:0.3.0") + implementation("space.kscience:kmath-functions:0.3.1-dev-1") } ``` diff --git a/kmath-geometry/README.md b/kmath-geometry/README.md index 6602f5510..72d275697 100644 --- a/kmath-geometry/README.md +++ b/kmath-geometry/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-geometry:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-geometry:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-geometry:0.3.0' + implementation 'space.kscience:kmath-geometry:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-geometry:0.3.0") + implementation("space.kscience:kmath-geometry:0.3.1-dev-1") } ``` diff --git a/kmath-histograms/README.md b/kmath-histograms/README.md index 27f1b43ec..5fd91ee0c 100644 --- a/kmath-histograms/README.md +++ b/kmath-histograms/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-histograms:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-histograms:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-histograms:0.3.0' + implementation 'space.kscience:kmath-histograms:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-histograms:0.3.0") + implementation("space.kscience:kmath-histograms:0.3.1-dev-1") } ``` diff --git a/kmath-jafama/README.md b/kmath-jafama/README.md index fe6afb835..c008c76ca 100644 --- a/kmath-jafama/README.md +++ b/kmath-jafama/README.md @@ -7,7 +7,7 @@ Integration with [Jafama](https://github.com/jeffhain/jafama). ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-jafama:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-jafama:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -17,7 +17,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-jafama:0.3.0' + implementation 'space.kscience:kmath-jafama:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -28,7 +28,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-jafama:0.3.0") + implementation("space.kscience:kmath-jafama:0.3.1-dev-1") } ``` diff --git a/kmath-jupyter/README.md b/kmath-jupyter/README.md index db58ad840..3c9832625 100644 --- a/kmath-jupyter/README.md +++ b/kmath-jupyter/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-jupyter:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-jupyter:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-jupyter:0.3.0' + implementation 'space.kscience:kmath-jupyter:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-jupyter:0.3.0") + implementation("space.kscience:kmath-jupyter:0.3.1-dev-1") } ``` diff --git a/kmath-kotlingrad/README.md b/kmath-kotlingrad/README.md index 52e8b3116..457652aaf 100644 --- a/kmath-kotlingrad/README.md +++ b/kmath-kotlingrad/README.md @@ -8,7 +8,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-kotlingrad:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-kotlingrad:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -18,7 +18,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-kotlingrad:0.3.0' + implementation 'space.kscience:kmath-kotlingrad:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -29,6 +29,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-kotlingrad:0.3.0") + implementation("space.kscience:kmath-kotlingrad:0.3.1-dev-1") } ``` diff --git a/kmath-memory/README.md b/kmath-memory/README.md index 9f4520bd8..536d7f145 100644 --- a/kmath-memory/README.md +++ b/kmath-memory/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-memory:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-memory:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-memory:0.3.0' + implementation 'space.kscience:kmath-memory:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-memory:0.3.0") + implementation("space.kscience:kmath-memory:0.3.1-dev-1") } ``` diff --git a/kmath-multik/README.md b/kmath-multik/README.md index edfce6f79..0f5b65b4c 100644 --- a/kmath-multik/README.md +++ b/kmath-multik/README.md @@ -6,7 +6,7 @@ JetBrains Multik connector ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-multik:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-multik:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-multik:0.3.0' + implementation 'space.kscience:kmath-multik:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-multik:0.3.0") + implementation("space.kscience:kmath-multik:0.3.1-dev-1") } ``` diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index 0bcae138e..bb065a300 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -9,7 +9,7 @@ ND4J based implementations of KMath abstractions. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-nd4j:0.3.0' + implementation 'space.kscience:kmath-nd4j:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -30,7 +30,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-nd4j:0.3.0") + implementation("space.kscience:kmath-nd4j:0.3.1-dev-1") } ``` diff --git a/kmath-optimization/README.md b/kmath-optimization/README.md index 63e0f43e3..d7441ebd1 100644 --- a/kmath-optimization/README.md +++ b/kmath-optimization/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-optimization:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-optimization:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-optimization:0.3.0' + implementation 'space.kscience:kmath-optimization:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-optimization:0.3.0") + implementation("space.kscience:kmath-optimization:0.3.1-dev-1") } ``` diff --git a/kmath-stat/README.md b/kmath-stat/README.md index 80c6e0fcd..7ed20fcf4 100644 --- a/kmath-stat/README.md +++ b/kmath-stat/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-stat:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-stat:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-stat:0.3.0' + implementation 'space.kscience:kmath-stat:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-stat:0.3.0") + implementation("space.kscience:kmath-stat:0.3.1-dev-1") } ``` diff --git a/kmath-symja/README.md b/kmath-symja/README.md index ea2d5d68f..a96b0e835 100644 --- a/kmath-symja/README.md +++ b/kmath-symja/README.md @@ -6,7 +6,7 @@ Symja integration module ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-symja:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-symja:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-symja:0.3.0' + implementation 'space.kscience:kmath-symja:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-symja:0.3.0") + implementation("space.kscience:kmath-symja:0.3.1-dev-1") } ``` diff --git a/kmath-tensorflow/README.md b/kmath-tensorflow/README.md index 7852c07be..83f2eb315 100644 --- a/kmath-tensorflow/README.md +++ b/kmath-tensorflow/README.md @@ -6,7 +6,7 @@ Google tensorflow connector ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-tensorflow:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-tensorflow:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-tensorflow:0.3.0' + implementation 'space.kscience:kmath-tensorflow:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-tensorflow:0.3.0") + implementation("space.kscience:kmath-tensorflow:0.3.1-dev-1") } ``` diff --git a/kmath-tensors/README.md b/kmath-tensors/README.md index 44ee47675..4208cd83d 100644 --- a/kmath-tensors/README.md +++ b/kmath-tensors/README.md @@ -9,7 +9,7 @@ Common linear algebra operations on tensors. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-tensors:0.3.0' + implementation 'space.kscience:kmath-tensors:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-tensors:0.3.0") + implementation("space.kscience:kmath-tensors:0.3.1-dev-1") } ``` diff --git a/kmath-trajectory/README.md b/kmath-trajectory/README.md index cb2b6989f..ac2930b04 100644 --- a/kmath-trajectory/README.md +++ b/kmath-trajectory/README.md @@ -1,12 +1,11 @@ -# Module kmath-trajectory +# kmath-trajectory -## Usage ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-trajectory:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-trajectory:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +15,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-trajectory:0.3.0' + implementation 'space.kscience:kmath-trajectory:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +26,9 @@ repositories { } dependencies { - implementation("space.kscience:kmath-trajectory:0.3.0") + 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 index 502867ee3..db80be02a 100644 --- a/kmath-trajectory/build.gradle.kts +++ b/kmath-trajectory/build.gradle.kts @@ -11,5 +11,7 @@ kotlin.sourceSets.commonMain { } readme { + description = "Path and trajectory optimization" maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) } diff --git a/kmath-trajectory/docs/README-TEMPLATE.md b/kmath-trajectory/docs/README-TEMPLATE.md new file mode 100644 index 000000000..eb8e4a0c0 --- /dev/null +++ b/kmath-trajectory/docs/README-TEMPLATE.md @@ -0,0 +1,13 @@ +# kmath-trajectory + + +${features} + +${artifact} + +## Author +Erik Schouten + +Github: ESchouten + +Email: erik-schouten@hotmail.nl diff --git a/kmath-viktor/README.md b/kmath-viktor/README.md index 5d7c2dea1..abff20427 100644 --- a/kmath-viktor/README.md +++ b/kmath-viktor/README.md @@ -6,7 +6,7 @@ Binding for https://github.com/JetBrains-Research/viktor ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-viktor:0.3.0`. +The Maven coordinates of this project are `space.kscience:kmath-viktor:0.3.1-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-viktor:0.3.0' + implementation 'space.kscience:kmath-viktor:0.3.1-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-viktor:0.3.0") + implementation("space.kscience:kmath-viktor:0.3.1-dev-1") } ``` -- 2.34.1 From 323e8b6872137eb6da1b8c91aff1ce8b4e8d31d7 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 26 Jul 2022 09:19:04 +0300 Subject: [PATCH 162/275] Code simplification for Dubins path --- .../space/kscience/kmath/geometry/Circle2D.kt | 18 ++++ .../space/kscience/kmath/geometry/Line.kt | 4 + .../kmath/trajectory/dubins/DubinsPath.kt | 82 +++++++++-------- ...oryFunctions.kt => trajectoryFunctions.kt} | 41 +++++---- .../kscience/kmath/trajectory/segments/Arc.kt | 59 ------------ .../kmath/trajectory/segments/Pose2D.kt | 21 +++++ .../kmath/trajectory/segments/Segment.kt | 5 -- .../kmath/trajectory/segments/Straight.kt | 18 ---- .../kmath/trajectory/segments/Trajectory.kt | 89 +++++++++++++++++++ .../trajectory/segments/components/Circle.kt | 11 --- .../trajectory/segments/components/Pose2D.kt | 13 --- .../space/kscience/kmath/trajectory/Math.kt | 10 +-- .../kmath/trajectory/dubins/DubinsTests.kt | 16 ++-- .../kmath/trajectory/segments/ArcTests.kt | 7 +- .../segments/{components => }/CircleTests.kt | 6 +- .../kmath/trajectory/segments/LineTests.kt | 12 +-- 16 files changed, 225 insertions(+), 187 deletions(-) create mode 100644 kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Circle2D.kt rename kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/{TrajectoryFunctions.kt => trajectoryFunctions.kt} (51%) delete mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt create mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Pose2D.kt delete mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Segment.kt delete mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Straight.kt create mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Trajectory.kt delete mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/components/Circle.kt delete mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/components/Pose2D.kt rename kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/{components => }/CircleTests.kt (74%) diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Circle2D.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Circle2D.kt new file mode 100644 index 000000000..8623335b9 --- /dev/null +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Circle2D.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.geometry + +import kotlin.math.PI + +/** + * A circle in 2D space + */ +public class Circle2D( + public val center: Vector2D, + public val radius: Double +) + +public val Circle2D.circumference: Double get() = radius * 2 * PI diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Line.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Line.kt index 8c6ccb55e..85bfcdd8f 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,6 +5,10 @@ package space.kscience.kmath.geometry +/** + * A line formed by [base] vector of start and a [direction] vector. Direction vector is not necessarily normalized, + * but its length does not affect line properties + */ public data class Line(val base: V, val direction: V) public typealias Line2D = Line diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPath.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPath.kt index ee4f38662..f510e3572 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPath.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPath.kt @@ -5,91 +5,95 @@ package space.kscience.kmath.trajectory.dubins +import space.kscience.kmath.geometry.Circle2D import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo import space.kscience.kmath.geometry.Vector2D -import space.kscience.kmath.trajectory.segments.Arc -import space.kscience.kmath.trajectory.segments.Segment -import space.kscience.kmath.trajectory.segments.Straight -import space.kscience.kmath.trajectory.segments.components.Circle -import space.kscience.kmath.trajectory.segments.components.Pose2D +import space.kscience.kmath.trajectory.segments.ArcSegment +import space.kscience.kmath.trajectory.segments.Pose2D +import space.kscience.kmath.trajectory.segments.StraightSegment +import space.kscience.kmath.trajectory.segments.Trajectory import kotlin.math.acos import kotlin.math.cos import kotlin.math.sin public class DubinsPath( - public val a: Arc, - public val b: Segment, - public val c: Arc, -) { + public val a: ArcSegment, + public val b: Trajectory, + public val c: ArcSegment, +) : Trajectory { public val type: TYPE = TYPE.valueOf( arrayOf( a.direction.name[0], - if (b is Arc) b.direction.name[0] else 'S', + if (b is ArcSegment) b.direction.name[0] else 'S', c.direction.name[0] ).toCharArray().concatToString() ) - public val length: Double = a.length + b.length + c.length + override val length: Double get() = a.length + b.length + c.length public enum class TYPE { RLR, LRL, RSR, LSL, RSL, LSR } public companion object { - public fun all(start: Pose2D, end: Pose2D, turningRadius: Double): List = - listOfNotNull( - rlr(start, end, turningRadius), - lrl(start, end, turningRadius), - rsr(start, end, turningRadius), - lsl(start, end, turningRadius), - rsl(start, end, turningRadius), - lsr(start, end, turningRadius) - ) + public fun all( + start: Pose2D, + end: Pose2D, + turningRadius: Double, + ): List = listOfNotNull( + rlr(start, end, turningRadius), + lrl(start, end, turningRadius), + rsr(start, end, turningRadius), + lsl(start, end, turningRadius), + rsl(start, end, turningRadius), + lsr(start, end, turningRadius) + ) + public fun shortest(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath = - all(start, end, turningRadius).minByOrNull { it.length }!! + all(start, end, turningRadius).minBy { it.length } public fun rlr(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath? { val c1 = start.getRightCircle(turningRadius) val c2 = end.getRightCircle(turningRadius) - val centers = Straight(c1.center, c2.center) + val centers = StraightSegment(c1.center, c2.center) if (centers.length > turningRadius * 4) return null var theta = theta(centers.theta - acos(centers.length / (turningRadius * 4))) var dX = turningRadius * sin(theta) var dY = turningRadius * cos(theta) val p = Vector2D(c1.center.x + dX * 2, c1.center.y + dY * 2) - val e = Circle(p, turningRadius) + val e = Circle2D(p, turningRadius) val p1 = Vector2D(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 = Vector2D(e.center.x + dX, e.center.y + dY) - val a1 = Arc.of(c1.center, start, p1, Arc.Direction.RIGHT) - val a2 = Arc.of(e.center, p1, p2, Arc.Direction.LEFT) - val a3 = Arc.of(c2.center, p2, end, Arc.Direction.RIGHT) + val a1 = ArcSegment.of(c1.center, start, p1, ArcSegment.Direction.RIGHT) + val a2 = ArcSegment.of(e.center, p1, p2, ArcSegment.Direction.LEFT) + val a3 = ArcSegment.of(c2.center, p2, end, ArcSegment.Direction.RIGHT) return DubinsPath(a1, a2, a3) } public fun lrl(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath? { val c1 = start.getLeftCircle(turningRadius) val c2 = end.getLeftCircle(turningRadius) - val centers = Straight(c1.center, c2.center) + val centers = StraightSegment(c1.center, c2.center) if (centers.length > turningRadius * 4) return null var theta = theta(centers.theta + acos(centers.length / (turningRadius * 4))) var dX = turningRadius * sin(theta) var dY = turningRadius * cos(theta) val p = Vector2D(c1.center.x + dX * 2, c1.center.y + dY * 2) - val e = Circle(p, turningRadius) + val e = Circle2D(p, turningRadius) val p1 = Vector2D(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 = Vector2D(e.center.x + dX, e.center.y + dY) - val a1 = Arc.of(c1.center, start, p1, Arc.Direction.LEFT) - val a2 = Arc.of(e.center, p1, p2, Arc.Direction.RIGHT) - val a3 = Arc.of(c2.center, p2, end, Arc.Direction.LEFT) + 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) } @@ -97,8 +101,8 @@ public class DubinsPath( val c1 = start.getRightCircle(turningRadius) val c2 = end.getRightCircle(turningRadius) val s = leftOuterTangent(c1, c2) - val a1 = Arc.of(c1.center, start, s.start, Arc.Direction.RIGHT) - val a3 = Arc.of(c2.center, s.end, end, Arc.Direction.RIGHT) + val a1 = ArcSegment.of(c1.center, start, s.start, ArcSegment.Direction.RIGHT) + val a3 = ArcSegment.of(c2.center, s.end, end, ArcSegment.Direction.RIGHT) return DubinsPath(a1, s, a3) } @@ -106,8 +110,8 @@ public class DubinsPath( val c1 = start.getLeftCircle(turningRadius) val c2 = end.getLeftCircle(turningRadius) val s = rightOuterTangent(c1, c2) - val a1 = Arc.of(c1.center, start, s.start, Arc.Direction.LEFT) - val a3 = Arc.of(c2.center, s.end, end, Arc.Direction.LEFT) + val a1 = ArcSegment.of(c1.center, start, s.start, ArcSegment.Direction.LEFT) + val a3 = ArcSegment.of(c2.center, s.end, end, ArcSegment.Direction.LEFT) return DubinsPath(a1, s, a3) } @@ -117,8 +121,8 @@ public class DubinsPath( val s = rightInnerTangent(c1, c2) if (c1.center.distanceTo(c2.center) < turningRadius * 2 || s == null) return null - val a1 = Arc.of(c1.center, start, s.start, Arc.Direction.RIGHT) - val a3 = Arc.of(c2.center, s.end, end, Arc.Direction.LEFT) + val a1 = ArcSegment.of(c1.center, start, s.start, ArcSegment.Direction.RIGHT) + val a3 = ArcSegment.of(c2.center, s.end, end, ArcSegment.Direction.LEFT) return DubinsPath(a1, s, a3) } @@ -128,8 +132,8 @@ public class DubinsPath( val s = leftInnerTangent(c1, c2) if (c1.center.distanceTo(c2.center) < turningRadius * 2 || s == null) return null - val a1 = Arc.of(c1.center, start, s.start, Arc.Direction.LEFT) - val a3 = Arc.of(c2.center, s.end, end, Arc.Direction.RIGHT) + val a1 = ArcSegment.of(c1.center, start, s.start, ArcSegment.Direction.LEFT) + val a3 = ArcSegment.of(c2.center, s.end, end, ArcSegment.Direction.RIGHT) return DubinsPath(a1, s, a3) } } diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/TrajectoryFunctions.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/trajectoryFunctions.kt similarity index 51% rename from kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/TrajectoryFunctions.kt rename to kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/trajectoryFunctions.kt index 547cb99fc..18384d349 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/TrajectoryFunctions.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/trajectoryFunctions.kt @@ -5,10 +5,10 @@ package space.kscience.kmath.trajectory.dubins +import space.kscience.kmath.geometry.Circle2D import space.kscience.kmath.geometry.Vector2D -import space.kscience.kmath.trajectory.segments.Straight -import space.kscience.kmath.trajectory.segments.components.Circle -import space.kscience.kmath.trajectory.segments.components.Pose2D +import space.kscience.kmath.trajectory.segments.Pose2D +import space.kscience.kmath.trajectory.segments.StraightSegment import kotlin.math.PI import kotlin.math.acos import kotlin.math.cos @@ -18,18 +18,19 @@ private enum class SIDE { LEFT, RIGHT } -internal fun Pose2D.getLeftCircle(radius: Double): Circle = getTangentCircles(radius).first -internal fun Pose2D.getRightCircle(radius: Double): Circle = getTangentCircles(radius).second -internal fun Pose2D.getTangentCircles(radius: Double): Pair { +internal fun Pose2D.getLeftCircle(radius: Double): Circle2D = getTangentCircles(radius).first +internal fun Pose2D.getRightCircle(radius: Double): Circle2D = getTangentCircles(radius).second +internal fun Pose2D.getTangentCircles(radius: Double): Pair { val dX = radius * cos(theta) val dY = radius * sin(theta) - return Circle(Vector2D(x - dX, y + dY), radius) to Circle(Vector2D(x + dX, y - dY), radius) + return Circle2D(Vector2D(x - dX, y + dY), radius) to Circle2D(Vector2D(x + dX, y - dY), radius) } -internal fun leftOuterTangent(a: Circle, b: Circle) = outerTangent(a, b, SIDE.LEFT) -internal fun rightOuterTangent(a: Circle, b: Circle) = outerTangent(a, b, SIDE.RIGHT) -private fun outerTangent(a: Circle, b: Circle, side: SIDE): Straight { - val centers = Straight(a.center, b.center) +internal fun leftOuterTangent(a: Circle2D, b: Circle2D): StraightSegment = outerTangent(a, b, SIDE.LEFT) +internal fun rightOuterTangent(a: Circle2D, b: Circle2D): StraightSegment = outerTangent(a, b, SIDE.RIGHT) + +private fun outerTangent(a: Circle2D, b: Circle2D, side: SIDE): StraightSegment { + val centers = StraightSegment(a.center, b.center) val p1 = when (side) { SIDE.LEFT -> Vector2D( a.center.x - a.radius * cos(centers.theta), @@ -40,16 +41,20 @@ private fun outerTangent(a: Circle, b: Circle, side: SIDE): Straight { a.center.y - a.radius * sin(centers.theta) ) } - return Straight( + return StraightSegment( p1, Vector2D(p1.x + (centers.end.x - centers.start.x), p1.y + (centers.end.y - centers.start.y)) ) } -internal fun leftInnerTangent(base: Circle, direction: Circle) = innerTangent(base, direction, SIDE.LEFT) -internal fun rightInnerTangent(base: Circle, direction: Circle) = innerTangent(base, direction, SIDE.RIGHT) -private fun innerTangent(base: Circle, direction: Circle, side: SIDE): Straight? { - val centers = Straight(base.center, direction.center) +internal fun leftInnerTangent(base: Circle2D, direction: Circle2D): StraightSegment? = + innerTangent(base, direction, SIDE.LEFT) + +internal fun rightInnerTangent(base: Circle2D, direction: Circle2D): StraightSegment? = + innerTangent(base, direction, SIDE.RIGHT) + +private fun innerTangent(base: Circle2D, direction: Circle2D, side: SIDE): StraightSegment? { + val centers = StraightSegment(base.center, direction.center) if (centers.length < base.radius * 2) return null val angle = theta( when (side) { @@ -61,7 +66,7 @@ private fun innerTangent(base: Circle, direction: Circle, side: SIDE): Straight? val dY = base.radius * cos(angle) val p1 = Vector2D(base.center.x + dX, base.center.y + dY) val p2 = Vector2D(direction.center.x - dX, direction.center.y - dY) - return Straight(p1, p2) + return StraightSegment(p1, p2) } -internal fun theta(theta: Double) = (theta + (2 * PI)) % (2 * PI) +internal fun theta(theta: Double): Double = (theta + (2 * PI)) % (2 * PI) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt deleted file mode 100644 index 1c02dd952..000000000 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Arc.kt +++ /dev/null @@ -1,59 +0,0 @@ -package space.kscience.kmath.trajectory.segments - -import space.kscience.kmath.geometry.Vector2D -import space.kscience.kmath.trajectory.dubins.theta -import space.kscience.kmath.trajectory.segments.components.Circle -import space.kscience.kmath.trajectory.segments.components.Pose2D -import kotlin.math.PI - -public data class Arc( - public val circle: Circle, - public val start: Pose2D, - public val end: Pose2D -) : Segment { - - internal companion object { - fun of(center: Vector2D, start: Vector2D, end: Vector2D, direction: Direction): Arc { - val s1 = Straight(center, start) - val s2 = Straight(center, end) - val pose1 = calculatePose(start, s1.theta, direction) - val pose2 = calculatePose(end, s2.theta, direction) - return Arc(Circle(center, s1.length), pose1, pose2) - } - - private fun calculatePose(vector: Vector2D, theta: Double, direction: Direction): Pose2D = - Pose2D.of( - vector, - when (direction) { - Direction.LEFT -> theta(theta - PI / 2) - Direction.RIGHT -> theta(theta + PI / 2) - } - ) - } - - internal enum class Direction { - LEFT, RIGHT - } - - override val length: Double - get() { - val angle: Double = - theta(if (direction == Direction.LEFT) start.theta - end.theta else end.theta - start.theta) - val proportion = angle / (2 * PI) - return circle.circumference * proportion - } - - internal val direction: Direction - get() = if (start.y < circle.center.y) { - if (start.theta > PI) Direction.RIGHT else Direction.LEFT - } else if (start.y > circle.center.y) { - if (start.theta < PI) Direction.RIGHT else Direction.LEFT - } else { - if (start.theta == 0.0) { - if (start.x < circle.center.x) Direction.RIGHT else Direction.LEFT - } else { - if (start.x > circle.center.x) Direction.RIGHT else Direction.LEFT - } - } - -} diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Pose2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Pose2D.kt new file mode 100644 index 000000000..3df34c107 --- /dev/null +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Pose2D.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.trajectory.segments + +import space.kscience.kmath.geometry.Vector2D + +/** + * A [Vector2D] with view direction + */ +public data class Pose2D( + override val x: Double, + override val y: Double, + public val theta: Double +) : Vector2D { + public companion object { + public fun of(vector: Vector2D, theta: Double): Pose2D = Pose2D(vector.x, vector.y, theta) + } +} diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Segment.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Segment.kt deleted file mode 100644 index 8a1d086fc..000000000 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Segment.kt +++ /dev/null @@ -1,5 +0,0 @@ -package space.kscience.kmath.trajectory.segments - -public interface Segment { - public val length: Double -} diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Straight.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Straight.kt deleted file mode 100644 index 444025d83..000000000 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Straight.kt +++ /dev/null @@ -1,18 +0,0 @@ -package space.kscience.kmath.trajectory.segments - -import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo -import space.kscience.kmath.geometry.Vector2D -import space.kscience.kmath.trajectory.dubins.theta -import kotlin.math.PI -import kotlin.math.atan2 - -public data class Straight( - internal val start: Vector2D, - internal val end: Vector2D -) : Segment { - override val length: Double - get() = start.distanceTo(end) - - internal val theta: Double - get() = theta(atan2(end.x - start.x, end.y - start.y)) -} diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Trajectory.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Trajectory.kt new file mode 100644 index 000000000..453eef47f --- /dev/null +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Trajectory.kt @@ -0,0 +1,89 @@ +package space.kscience.kmath.trajectory.segments + +import space.kscience.kmath.geometry.Circle2D +import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo +import space.kscience.kmath.geometry.Vector2D +import space.kscience.kmath.geometry.circumference +import space.kscience.kmath.trajectory.dubins.theta +import kotlin.math.PI +import kotlin.math.atan2 + +public interface Trajectory { + public val length: Double +} + +/** + * Straight path segment. The order of start and end defines the direction + */ +public data class StraightSegment( + internal val start: Vector2D, + internal val end: Vector2D, +) : Trajectory { + override val length: Double get() = start.distanceTo(end) + + internal val theta: Double get() = theta(atan2(end.x - start.x, end.y - start.y)) +} + +/** + * An arc segment + */ +public data class ArcSegment( + public val circle: Circle2D, + public val start: Pose2D, + public val end: Pose2D, +) : Trajectory { + + public enum class Direction { + LEFT, RIGHT + } + + override val length: Double by lazy { + val angle: Double = theta( + if (direction == Direction.LEFT) { + start.theta - end.theta + } else { + end.theta - start.theta + } + ) + val proportion = angle / (2 * PI) + circle.circumference * proportion + } + + internal val direction: Direction by lazy { + if (start.y < circle.center.y) { + if (start.theta > PI) Direction.RIGHT else Direction.LEFT + } else if (start.y > circle.center.y) { + if (start.theta < PI) Direction.RIGHT else Direction.LEFT + } else { + if (start.theta == 0.0) { + if (start.x < circle.center.x) Direction.RIGHT else Direction.LEFT + } else { + if (start.x > circle.center.x) Direction.RIGHT else Direction.LEFT + } + } + } + + public companion object { + public fun of(center: Vector2D, start: Vector2D, end: Vector2D, direction: Direction): ArcSegment { + fun calculatePose( + vector: Vector2D, + theta: Double, + direction: Direction, + ): Pose2D = Pose2D.of( + vector, + when (direction) { + Direction.LEFT -> theta(theta - PI / 2) + Direction.RIGHT -> theta(theta + PI / 2) + } + ) + + val s1 = StraightSegment(center, start) + val s2 = StraightSegment(center, end) + val pose1 = calculatePose(start, s1.theta, direction) + val pose2 = calculatePose(end, s2.theta, direction) + return ArcSegment(Circle2D(center, s1.length), pose1, pose2) + } + } + +} + diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/components/Circle.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/components/Circle.kt deleted file mode 100644 index 946dd8c6e..000000000 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/components/Circle.kt +++ /dev/null @@ -1,11 +0,0 @@ -package space.kscience.kmath.trajectory.segments.components - -import space.kscience.kmath.geometry.Vector2D -import kotlin.math.PI - -public open class Circle( - internal val center: Vector2D, - internal val radius: Double -) { - internal val circumference = radius * 2 * PI -} diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/components/Pose2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/components/Pose2D.kt deleted file mode 100644 index c49da3187..000000000 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/components/Pose2D.kt +++ /dev/null @@ -1,13 +0,0 @@ -package space.kscience.kmath.trajectory.segments.components - -import space.kscience.kmath.geometry.Vector2D - -public data class Pose2D( - override val x: Double, - override val y: Double, - public val theta: Double -) : Vector2D { - internal companion object { - internal fun of(vector: Vector2D, theta: Double) = Pose2D(vector.x, vector.y, theta) - } -} 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 92b2f1df9..4f8fda826 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 @@ -1,8 +1,8 @@ package space.kscience.kmath.trajectory import space.kscience.kmath.geometry.Vector2D -import space.kscience.kmath.trajectory.segments.Straight -import space.kscience.kmath.trajectory.segments.components.Pose2D +import space.kscience.kmath.trajectory.segments.Pose2D +import space.kscience.kmath.trajectory.segments.StraightSegment import kotlin.math.PI import kotlin.math.abs import kotlin.math.sin @@ -14,12 +14,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 Straight.inverse() = Straight(end, start) -fun Straight.shift(shift: Int, width: Double): Straight { +fun StraightSegment.inverse() = StraightSegment(end, start) +fun StraightSegment.shift(shift: Int, width: Double): StraightSegment { val dX = width * sin(inverse().theta) val dY = width * sin(theta) - return Straight( + return StraightSegment( Vector2D(start.x - dX * shift, start.y - dY * shift), Vector2D(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 47e6ac2ef..9069f6dd2 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 @@ -10,9 +10,9 @@ import space.kscience.kmath.geometry.Vector2D import space.kscience.kmath.trajectory.equalFloat import space.kscience.kmath.trajectory.equalsFloat import space.kscience.kmath.trajectory.inverse -import space.kscience.kmath.trajectory.segments.Arc -import space.kscience.kmath.trajectory.segments.Straight -import space.kscience.kmath.trajectory.segments.components.Pose2D +import space.kscience.kmath.trajectory.segments.ArcSegment +import space.kscience.kmath.trajectory.segments.Pose2D +import space.kscience.kmath.trajectory.segments.StraightSegment import space.kscience.kmath.trajectory.shift import kotlin.test.Test import kotlin.test.assertNotNull @@ -23,7 +23,7 @@ class DubinsTests { @Test fun dubinsTest() { - val straight = Straight(Vector2D(0.0, 0.0), Vector2D(100.0, 100.0)) + val straight = StraightSegment(Vector2D(0.0, 0.0), Vector2D(100.0, 100.0)) val lineP1 = straight.shift(1, 10.0).inverse() val start = Pose2D.of(straight.end, straight.theta) @@ -52,12 +52,12 @@ class DubinsTests { assertTrue(end.equalsFloat(path.c.end)) // Not working, theta double precision inaccuracy - if (path.b is Arc) { - val b = path.b as Arc + if (path.b is ArcSegment) { + val b = path.b as ArcSegment assertTrue(path.a.end.equalsFloat(b.start)) assertTrue(path.c.start.equalsFloat(b.end)) - } else if (path.b is Straight) { - val b = path.b as Straight + } else if (path.b is StraightSegment) { + val b = path.b as StraightSegment assertTrue(path.a.end.equalsFloat(Pose2D.of(b.start, b.theta))) assertTrue(path.c.start.equalsFloat(Pose2D.of(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 5b4ae6d7a..aa8778315 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 @@ -1,8 +1,9 @@ package space.kscience.kmath.trajectory.segments +import space.kscience.kmath.geometry.Circle2D import space.kscience.kmath.geometry.Vector2D +import space.kscience.kmath.geometry.circumference import space.kscience.kmath.trajectory.radiansToDegrees -import space.kscience.kmath.trajectory.segments.components.Circle import kotlin.test.Test import kotlin.test.assertEquals @@ -10,8 +11,8 @@ class ArcTests { @Test fun arcTest() { - val circle = Circle(Vector2D(0.0, 0.0), 2.0) - val arc = Arc.of(circle.center, Vector2D(-2.0, 0.0), Vector2D(0.0, 2.0), Arc.Direction.RIGHT) + val circle = Circle2D(Vector2D(0.0, 0.0), 2.0) + val arc = ArcSegment.of(circle.center, Vector2D(-2.0, 0.0), Vector2D(0.0, 2.0), ArcSegment.Direction.RIGHT) assertEquals(circle.circumference / 4, arc.length, 1.0) assertEquals(0.0, arc.start.theta.radiansToDegrees()) assertEquals(90.0, arc.end.theta.radiansToDegrees()) diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/components/CircleTests.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/CircleTests.kt similarity index 74% rename from kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/components/CircleTests.kt rename to kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/CircleTests.kt index 6f28885e0..5170c1db5 100644 --- a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/components/CircleTests.kt +++ b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/CircleTests.kt @@ -3,9 +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.trajectory.segments.components +package space.kscience.kmath.trajectory.segments +import space.kscience.kmath.geometry.Circle2D import space.kscience.kmath.geometry.Vector2D +import space.kscience.kmath.geometry.circumference import space.kscience.kmath.trajectory.maxFloatDelta import kotlin.test.Test import kotlin.test.assertEquals @@ -17,7 +19,7 @@ class CircleTests { val center = Vector2D(0.0, 0.0) val radius = 2.0 val expectedCircumference = 12.56637 - val circle = Circle(center, radius) + val circle = Circle2D(center, radius) assertEquals(expectedCircumference, circle.circumference, maxFloatDelta) } } diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/LineTests.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/LineTests.kt index e8184e178..afc473d79 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 @@ -12,21 +12,21 @@ class LineTests { @Test fun lineTest() { - val straight = Straight(Vector2D(0.0, 0.0), Vector2D(100.0, 100.0)) + val straight = StraightSegment(Vector2D(0.0, 0.0), Vector2D(100.0, 100.0)) assertEquals(sqrt(100.0.pow(2) + 100.0.pow(2)), straight.length) assertEquals(45.0, straight.theta.radiansToDegrees()) } @Test fun lineAngleTest() { - val zero = Vector2D(0.0, 0.0) - val north = Straight(Euclidean2DSpace.zero, Vector2D(0.0, 2.0)) + //val zero = Vector2D(0.0, 0.0) + val north = StraightSegment(Euclidean2DSpace.zero, Vector2D(0.0, 2.0)) assertEquals(0.0, north.theta.radiansToDegrees()) - val east = Straight(Euclidean2DSpace.zero, Vector2D(2.0, 0.0)) + val east = StraightSegment(Euclidean2DSpace.zero, Vector2D(2.0, 0.0)) assertEquals(90.0, east.theta.radiansToDegrees()) - val south = Straight(Euclidean2DSpace.zero, Vector2D(0.0, -2.0)) + val south = StraightSegment(Euclidean2DSpace.zero, Vector2D(0.0, -2.0)) assertEquals(180.0, south.theta.radiansToDegrees()) - val west = Straight(Euclidean2DSpace.zero, Vector2D(-2.0, 0.0)) + val west = StraightSegment(Euclidean2DSpace.zero, Vector2D(-2.0, 0.0)) assertEquals(270.0, west.theta.radiansToDegrees()) } } -- 2.34.1 From c2025ee1c9f1323b446f992a8f80b302bcd46774 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Wed, 27 Jul 2022 14:31:55 +0300 Subject: [PATCH 163/275] Remove Polynomial interface, fix consequent platform clashes. Add invariance. --- .../kmath/functions/LabeledPolynomial.kt | 4 +- .../kmath/functions/ListPolynomial.kt | 4 +- .../kmath/functions/NumberedPolynomial.kt | 4 +- .../kscience/kmath/functions/Polynomial.kt | 41 ++++-- .../kmath/functions/RationalFunction.kt | 130 ++++++++++++++++-- 5 files changed, 160 insertions(+), 23 deletions(-) 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 index e2320114b..6a4d1409f 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -19,7 +19,7 @@ import kotlin.math.max * * @param C the type of constants. */ -public data class LabeledPolynomial +public data class LabeledPolynomial @PublishedApi internal constructor( /** @@ -63,7 +63,7 @@ internal constructor( * @usesMathJax */ public val coefficients: Map, C> -) : Polynomial { +) { override fun toString(): String = "LabeledPolynomial$coefficients" } 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 index d0e58c0d6..6ab660b63 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt @@ -19,7 +19,7 @@ import kotlin.math.min * * @param C the type of constants. */ -public data class ListPolynomial( +public data class ListPolynomial( /** * List that contains coefficients of the polynomial. * @@ -48,7 +48,7 @@ public data class ListPolynomial( * @usesMathJax */ public val coefficients: List -) : Polynomial { +) { override fun toString(): String = "ListPolynomial$coefficients" } 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 index d2fc5ffa1..267bbd91d 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -18,7 +18,7 @@ import kotlin.math.max * * @param C the type of constants. */ -public data class NumberedPolynomial +public data class NumberedPolynomial @PublishedApi internal constructor( /** @@ -47,7 +47,7 @@ internal constructor( * @usesMathJax */ public val coefficients: Map, C> -) : Polynomial { +) { override fun toString(): String = "NumberedPolynomial$coefficients" } 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 index 66308a7bc..6a11eb1bd 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -11,11 +11,6 @@ import kotlin.js.JsName import kotlin.jvm.JvmName -/** - * Abstraction of polynomials. - */ -public interface Polynomial - /** * Abstraction of ring of polynomials of type [P] over ring of constants of type [C]. * @@ -23,24 +18,27 @@ public interface Polynomial * @param P the type of polynomials. */ @Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") // FIXME: Waiting for KT-31420 -public interface PolynomialSpace> : Ring

{ +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 /** @@ -48,18 +46,21 @@ public interface PolynomialSpace> : Ring

{ * * 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 /** @@ -167,27 +168,33 @@ public interface PolynomialSpace> : Ring

{ /** * 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 /** @@ -252,7 +259,7 @@ public interface PolynomialSpace> : Ring

{ * @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, out A: Ring> : PolynomialSpace { +public interface PolynomialSpaceOverRing> : PolynomialSpace { /** * Underlying ring of constants. Its operations on constants are inherited by local operations on constants. @@ -264,18 +271,21 @@ public interface PolynomialSpaceOverRing, out A: 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) } /** @@ -283,18 +293,21 @@ public interface PolynomialSpaceOverRing, out A: Ring> : * * 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) } /** @@ -341,69 +354,81 @@ public interface PolynomialSpaceOverRing, out A: Ring> : * @param P the type of polynomials. */ @Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 -public interface MultivariatePolynomialSpace>: PolynomialSpace { +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 /** 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 index da91c8d61..3c1548516 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -14,7 +14,7 @@ import kotlin.jvm.JvmName /** * Abstraction of rational function. */ -public interface RationalFunction> { +public interface RationalFunction { public val numerator: P public val denominator: P public operator fun component1(): P = numerator @@ -30,24 +30,27 @@ public interface RationalFunction> { * @param R the type of rational functions. */ @Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") // FIXME: Waiting for KT-31420 -public interface RationalFunctionSpace, R: RationalFunction> : Ring { +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 /** @@ -55,18 +58,21 @@ public interface RationalFunctionSpace, R: RationalFunction< * * 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 /** @@ -83,18 +89,21 @@ public interface RationalFunctionSpace, R: RationalFunction< * * 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 /** @@ -102,18 +111,21 @@ public interface RationalFunctionSpace, R: RationalFunction< * * 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 /** @@ -235,27 +247,33 @@ public interface RationalFunctionSpace, R: RationalFunction< /** * 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 /** @@ -270,30 +288,37 @@ public interface RationalFunctionSpace, R: RationalFunction< /** * 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 /** @@ -308,87 +333,107 @@ public interface RationalFunctionSpace, R: RationalFunction< /** * 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) /** @@ -462,7 +507,7 @@ public interface RationalFunctionSpace, R: RationalFunction< @Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 public interface RationalFunctionSpaceOverRing< C, - P: Polynomial, + P, R: RationalFunction, out A: Ring > : RationalFunctionSpace { @@ -477,18 +522,21 @@ public interface RationalFunctionSpaceOverRing< * * 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) } /** @@ -496,18 +544,21 @@ public interface RationalFunctionSpaceOverRing< * * 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) } /** @@ -564,7 +615,7 @@ public interface RationalFunctionSpaceOverRing< @Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 public interface RationalFunctionSpaceOverPolynomialSpace< C, - P: Polynomial, + P, R: RationalFunction, out AP: PolynomialSpace, > : RationalFunctionSpace { @@ -579,18 +630,21 @@ public interface RationalFunctionSpaceOverPolynomialSpace< * * 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 } /** @@ -598,18 +652,21 @@ public interface RationalFunctionSpaceOverPolynomialSpace< * * 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 } /** @@ -626,18 +683,21 @@ public interface RationalFunctionSpaceOverPolynomialSpace< * * 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 } /** @@ -645,18 +705,21 @@ public interface RationalFunctionSpaceOverPolynomialSpace< * * 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 } /** @@ -711,27 +774,33 @@ public interface RationalFunctionSpaceOverPolynomialSpace< /** * 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 } /** @@ -746,26 +815,32 @@ public interface RationalFunctionSpaceOverPolynomialSpace< /** * 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) } /** @@ -796,7 +871,7 @@ public interface RationalFunctionSpaceOverPolynomialSpace< @Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420 public abstract class PolynomialSpaceOfFractions< C, - P: Polynomial, + P, R: RationalFunction, > : RationalFunctionSpace { @@ -897,11 +972,13 @@ public abstract class PolynomialSpaceOfFractions< /** * 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, @@ -910,6 +987,7 @@ public abstract class PolynomialSpaceOfFractions< /** * 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, @@ -918,6 +996,7 @@ public abstract class PolynomialSpaceOfFractions< /** * 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, @@ -926,6 +1005,7 @@ public abstract class PolynomialSpaceOfFractions< /** * 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, @@ -935,6 +1015,7 @@ public abstract class PolynomialSpaceOfFractions< /** * 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, @@ -943,6 +1024,7 @@ public abstract class PolynomialSpaceOfFractions< /** * 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, @@ -951,6 +1033,7 @@ public abstract class PolynomialSpaceOfFractions< /** * 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, @@ -959,6 +1042,7 @@ public abstract class PolynomialSpaceOfFractions< /** * 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, @@ -968,11 +1052,13 @@ public abstract class PolynomialSpaceOfFractions< /** * 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, @@ -981,6 +1067,7 @@ public abstract class PolynomialSpaceOfFractions< /** * 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, @@ -989,6 +1076,7 @@ public abstract class PolynomialSpaceOfFractions< /** * 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, @@ -997,6 +1085,7 @@ public abstract class PolynomialSpaceOfFractions< /** * 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, @@ -1006,6 +1095,7 @@ public abstract class PolynomialSpaceOfFractions< /** * 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, @@ -1014,6 +1104,7 @@ public abstract class PolynomialSpaceOfFractions< /** * 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, @@ -1022,6 +1113,7 @@ public abstract class PolynomialSpaceOfFractions< /** * 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, @@ -1030,6 +1122,7 @@ public abstract class PolynomialSpaceOfFractions< /** * 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, @@ -1039,6 +1132,7 @@ public abstract class PolynomialSpaceOfFractions< /** * Converts the polynomial [value] to rational function. */ + @JvmName("numberPolynomial") public override fun number(value: P): R = constructRationalFunction(value) /** @@ -1110,97 +1204,114 @@ public abstract class PolynomialSpaceOfFractions< public interface MultivariateRationalFunctionSpace< C, V, - P: Polynomial, + 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 /** @@ -1218,11 +1329,13 @@ public interface MultivariateRationalFunctionSpace< * 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) /** @@ -1339,7 +1452,7 @@ public interface MultivariateRationalFunctionSpace< public interface MultivariateRationalFunctionSpaceOverMultivariatePolynomialSpace< C, V, - P: Polynomial, + P, R: RationalFunction, out AP: MultivariatePolynomialSpace, > : RationalFunctionSpaceOverPolynomialSpace, MultivariateRationalFunctionSpace { @@ -1516,7 +1629,7 @@ public interface MultivariateRationalFunctionSpaceOverMultivariatePolynomialSpac public abstract class MultivariatePolynomialSpaceOfFractions< C, V, - P: Polynomial, + P, R: RationalFunction, > : MultivariateRationalFunctionSpace, PolynomialSpaceOfFractions() { /** @@ -1568,7 +1681,6 @@ public abstract class MultivariatePolynomialSpaceOfFractions< /** * Returns product of the rational function and the variable represented as a rational function. */ - @JvmName("timesRationalVariable") public override operator fun R.times(other: V): R = constructRationalFunction( numerator * other, -- 2.34.1 From 137ddb3ade4f57ee11d2fb05defaa68829d93925 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 29 Jul 2022 14:12:44 +0300 Subject: [PATCH 164/275] Code simplification for Dubins path --- .../trajectory/{dubins => }/DubinsPath.kt | 75 ++++++++++++++++--- .../space/kscience/kmath/trajectory/Pose2D.kt | 33 ++++++++ .../trajectory/{segments => }/Trajectory.kt | 17 +++-- .../kmath/trajectory/TrajectoryCost.kt | 14 ++++ .../trajectory/dubins/trajectoryFunctions.kt | 72 ------------------ .../space/kscience/kmath/trajectory/route.kt | 16 ++++ .../kmath/trajectory/segments/Pose2D.kt | 21 ------ .../space/kscience/kmath/trajectory/Math.kt | 2 - .../kmath/trajectory/dubins/DubinsTests.kt | 16 ++-- .../kmath/trajectory/segments/ArcTests.kt | 1 + .../kmath/trajectory/segments/LineTests.kt | 1 + 11 files changed, 146 insertions(+), 122 deletions(-) rename kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/{dubins => }/DubinsPath.kt (67%) create mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Pose2D.kt rename kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/{segments => }/Trajectory.kt (85%) create mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/TrajectoryCost.kt delete mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/trajectoryFunctions.kt create mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/route.kt delete mode 100644 kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Pose2D.kt diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPath.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt similarity index 67% rename from kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPath.kt rename to kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt index f510e3572..134342b33 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/DubinsPath.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt @@ -3,24 +3,79 @@ * 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.Circle2D import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo import space.kscience.kmath.geometry.Vector2D -import space.kscience.kmath.trajectory.segments.ArcSegment -import space.kscience.kmath.trajectory.segments.Pose2D -import space.kscience.kmath.trajectory.segments.StraightSegment -import space.kscience.kmath.trajectory.segments.Trajectory +import kotlin.math.PI import kotlin.math.acos import kotlin.math.cos import kotlin.math.sin +internal fun Pose2D.getLeftCircle(radius: Double): Circle2D = getTangentCircles(radius).first + +internal fun Pose2D.getRightCircle(radius: Double): Circle2D = getTangentCircles(radius).second + +internal fun Pose2D.getTangentCircles(radius: Double): Pair { + val dX = radius * cos(theta) + val dY = radius * sin(theta) + return Circle2D(Vector2D(x - dX, y + dY), radius) to Circle2D(Vector2D(x + dX, y - dY), radius) +} + +internal fun leftOuterTangent(a: Circle2D, b: Circle2D): StraightSegment = outerTangent(a, b, ArcSegment.Direction.LEFT) + +internal fun rightOuterTangent(a: Circle2D, b: Circle2D): StraightSegment = outerTangent(a, b, + ArcSegment.Direction.RIGHT +) + +private fun outerTangent(a: Circle2D, b: Circle2D, side: ArcSegment.Direction): StraightSegment { + val centers = StraightSegment(a.center, b.center) + val p1 = when (side) { + ArcSegment.Direction.LEFT -> Vector2D( + a.center.x - a.radius * cos(centers.theta), + a.center.y + a.radius * sin(centers.theta) + ) + ArcSegment.Direction.RIGHT -> Vector2D( + a.center.x + a.radius * cos(centers.theta), + a.center.y - a.radius * sin(centers.theta) + ) + } + return StraightSegment( + p1, + Vector2D(p1.x + (centers.end.x - centers.start.x), p1.y + (centers.end.y - centers.start.y)) + ) +} + +internal fun leftInnerTangent(base: Circle2D, direction: Circle2D): StraightSegment? = + innerTangent(base, direction, ArcSegment.Direction.LEFT) + +internal fun rightInnerTangent(base: Circle2D, direction: Circle2D): StraightSegment? = + innerTangent(base, direction, ArcSegment.Direction.RIGHT) + +private fun innerTangent(base: Circle2D, direction: Circle2D, side: ArcSegment.Direction): StraightSegment? { + val centers = StraightSegment(base.center, direction.center) + if (centers.length < base.radius * 2) return null + val angle = theta( + when (side) { + ArcSegment.Direction.LEFT -> centers.theta + acos(base.radius * 2 / centers.length) + ArcSegment.Direction.RIGHT -> centers.theta - acos(base.radius * 2 / centers.length) + } + ) + val dX = base.radius * sin(angle) + val dY = base.radius * cos(angle) + val p1 = Vector2D(base.center.x + dX, base.center.y + dY) + val p2 = Vector2D(direction.center.x - dX, direction.center.y - dY) + return StraightSegment(p1, p2) +} + +internal fun theta(theta: Double): Double = (theta + (2 * PI)) % (2 * PI) + public class DubinsPath( public val a: ArcSegment, public val b: Trajectory, public val c: ArcSegment, -) : Trajectory { +) : CompositeTrajectory(listOf(a,b,c)) { public val type: TYPE = TYPE.valueOf( arrayOf( @@ -30,8 +85,6 @@ public class DubinsPath( ).toCharArray().concatToString() ) - override val length: Double get() = a.length + b.length + c.length - public enum class TYPE { RLR, LRL, RSR, LSL, RSL, LSR } @@ -119,7 +172,7 @@ public class DubinsPath( val c1 = start.getRightCircle(turningRadius) val c2 = end.getLeftCircle(turningRadius) val s = rightInnerTangent(c1, c2) - if (c1.center.distanceTo(c2.center) < turningRadius * 2 || s == null) return null + 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) @@ -130,11 +183,11 @@ public class DubinsPath( val c1 = start.getLeftCircle(turningRadius) val c2 = end.getRightCircle(turningRadius) val s = leftInnerTangent(c1, c2) - if (c1.center.distanceTo(c2.center) < turningRadius * 2 || s == null) return null + if (s == null || c1.center.distanceTo(c2.center) < turningRadius * 2) return null val a1 = ArcSegment.of(c1.center, start, s.start, ArcSegment.Direction.LEFT) val a3 = ArcSegment.of(c2.center, s.end, end, ArcSegment.Direction.RIGHT) return DubinsPath(a1, s, a3) } } -} +} \ No newline at end of file diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Pose2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Pose2D.kt new file mode 100644 index 000000000..1f7c4a52e --- /dev/null +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Pose2D.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.trajectory + +import space.kscience.kmath.geometry.Vector +import space.kscience.kmath.geometry.Vector2D +import kotlin.math.atan2 + +/** + * Combination of [Vector] and its view angle + */ +public interface Pose2D: Vector2D{ + public val coordinate: Vector2D + public val theta: Double +} + +public class PhaseVector2D( + override val coordinate: Vector2D, + public val velocity: Vector2D +): Pose2D, Vector2D by coordinate{ + override val theta: Double get() = atan2(velocity.y, velocity.x) +} + +internal class Pose2DImpl( + override val coordinate: Vector2D, + override val theta: Double +) : Pose2D, Vector2D by coordinate + + +public fun Pose2D(coordinate: Vector2D, theta: Double): Pose2D = Pose2DImpl(coordinate, theta) \ No newline at end of file diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Trajectory.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory.kt similarity index 85% rename from kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Trajectory.kt rename to kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory.kt index 453eef47f..2e97d43b0 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Trajectory.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory.kt @@ -1,14 +1,18 @@ -package space.kscience.kmath.trajectory.segments +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.trajectory import space.kscience.kmath.geometry.Circle2D import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo import space.kscience.kmath.geometry.Vector2D import space.kscience.kmath.geometry.circumference -import space.kscience.kmath.trajectory.dubins.theta import kotlin.math.PI import kotlin.math.atan2 -public interface Trajectory { +public sealed interface Trajectory { public val length: Double } @@ -69,7 +73,7 @@ public data class ArcSegment( vector: Vector2D, theta: Double, direction: Direction, - ): Pose2D = Pose2D.of( + ): Pose2D = Pose2D( vector, when (direction) { Direction.LEFT -> theta(theta - PI / 2) @@ -84,6 +88,9 @@ public data class ArcSegment( return ArcSegment(Circle2D(center, s1.length), pose1, pose2) } } - +} + +public open class CompositeTrajectory(public val segments: Collection) : Trajectory { + override val length: Double get() = segments.sumOf { it.length } } diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/TrajectoryCost.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/TrajectoryCost.kt new file mode 100644 index 000000000..170851c43 --- /dev/null +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/TrajectoryCost.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.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/dubins/trajectoryFunctions.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/trajectoryFunctions.kt deleted file mode 100644 index 18384d349..000000000 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/dubins/trajectoryFunctions.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.trajectory.dubins - -import space.kscience.kmath.geometry.Circle2D -import space.kscience.kmath.geometry.Vector2D -import space.kscience.kmath.trajectory.segments.Pose2D -import space.kscience.kmath.trajectory.segments.StraightSegment -import kotlin.math.PI -import kotlin.math.acos -import kotlin.math.cos -import kotlin.math.sin - -private enum class SIDE { - LEFT, RIGHT -} - -internal fun Pose2D.getLeftCircle(radius: Double): Circle2D = getTangentCircles(radius).first -internal fun Pose2D.getRightCircle(radius: Double): Circle2D = getTangentCircles(radius).second -internal fun Pose2D.getTangentCircles(radius: Double): Pair { - val dX = radius * cos(theta) - val dY = radius * sin(theta) - return Circle2D(Vector2D(x - dX, y + dY), radius) to Circle2D(Vector2D(x + dX, y - dY), radius) -} - -internal fun leftOuterTangent(a: Circle2D, b: Circle2D): StraightSegment = outerTangent(a, b, SIDE.LEFT) -internal fun rightOuterTangent(a: Circle2D, b: Circle2D): StraightSegment = outerTangent(a, b, SIDE.RIGHT) - -private fun outerTangent(a: Circle2D, b: Circle2D, side: SIDE): StraightSegment { - val centers = StraightSegment(a.center, b.center) - val p1 = when (side) { - SIDE.LEFT -> Vector2D( - a.center.x - a.radius * cos(centers.theta), - a.center.y + a.radius * sin(centers.theta) - ) - SIDE.RIGHT -> Vector2D( - a.center.x + a.radius * cos(centers.theta), - a.center.y - a.radius * sin(centers.theta) - ) - } - return StraightSegment( - p1, - Vector2D(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, SIDE.LEFT) - -internal fun rightInnerTangent(base: Circle2D, direction: Circle2D): StraightSegment? = - innerTangent(base, direction, SIDE.RIGHT) - -private fun innerTangent(base: Circle2D, direction: Circle2D, side: SIDE): StraightSegment? { - val centers = StraightSegment(base.center, direction.center) - if (centers.length < base.radius * 2) return null - val angle = theta( - when (side) { - SIDE.LEFT -> centers.theta + acos(base.radius * 2 / centers.length) - SIDE.RIGHT -> centers.theta - acos(base.radius * 2 / centers.length) - } - ) - val dX = base.radius * sin(angle) - val dY = base.radius * cos(angle) - val p1 = Vector2D(base.center.x + dX, base.center.y + dY) - val p2 = Vector2D(direction.center.x - dX, direction.center.y - dY) - return StraightSegment(p1, p2) -} - -internal fun theta(theta: Double): Double = (theta + (2 * PI)) % (2 * PI) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/route.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/route.kt new file mode 100644 index 000000000..f67ab124d --- /dev/null +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/route.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.trajectory + +public fun interface MaxCurvature { + public fun compute(startPoint: PhaseVector2D): Double +} + +public fun DubinsPath.Companion.shortest( + start: PhaseVector2D, + end: PhaseVector2D, + computer: MaxCurvature, +): DubinsPath = shortest(start, end, computer.compute(start)) diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Pose2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Pose2D.kt deleted file mode 100644 index 3df34c107..000000000 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/segments/Pose2D.kt +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package space.kscience.kmath.trajectory.segments - -import space.kscience.kmath.geometry.Vector2D - -/** - * A [Vector2D] with view direction - */ -public data class Pose2D( - override val x: Double, - override val y: Double, - public val theta: Double -) : Vector2D { - public companion object { - public fun of(vector: Vector2D, theta: Double): Pose2D = Pose2D(vector.x, vector.y, theta) - } -} 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 4f8fda826..7ee68bd92 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 @@ -1,8 +1,6 @@ package space.kscience.kmath.trajectory import space.kscience.kmath.geometry.Vector2D -import space.kscience.kmath.trajectory.segments.Pose2D -import space.kscience.kmath.trajectory.segments.StraightSegment import kotlin.math.PI import kotlin.math.abs import kotlin.math.sin 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 9069f6dd2..09375a400 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 @@ -7,13 +7,7 @@ package space.kscience.kmath.trajectory.dubins import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo import space.kscience.kmath.geometry.Vector2D -import space.kscience.kmath.trajectory.equalFloat -import space.kscience.kmath.trajectory.equalsFloat -import space.kscience.kmath.trajectory.inverse -import space.kscience.kmath.trajectory.segments.ArcSegment -import space.kscience.kmath.trajectory.segments.Pose2D -import space.kscience.kmath.trajectory.segments.StraightSegment -import space.kscience.kmath.trajectory.shift +import space.kscience.kmath.trajectory.* import kotlin.test.Test import kotlin.test.assertNotNull import kotlin.test.assertTrue @@ -26,8 +20,8 @@ class DubinsTests { val straight = StraightSegment(Vector2D(0.0, 0.0), Vector2D(100.0, 100.0)) val lineP1 = straight.shift(1, 10.0).inverse() - val start = Pose2D.of(straight.end, straight.theta) - val end = Pose2D.of(lineP1.start, lineP1.theta) + val start = Pose2D(straight.end, straight.theta) + val end = Pose2D(lineP1.start, lineP1.theta) val radius = 2.0 val dubins = DubinsPath.all(start, end, radius) @@ -58,8 +52,8 @@ class DubinsTests { assertTrue(path.c.start.equalsFloat(b.end)) } else if (path.b is StraightSegment) { val b = path.b as StraightSegment - assertTrue(path.a.end.equalsFloat(Pose2D.of(b.start, b.theta))) - assertTrue(path.c.start.equalsFloat(Pose2D.of(b.end, b.theta))) + 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 aa8778315..c66fa201b 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 @@ -3,6 +3,7 @@ package space.kscience.kmath.trajectory.segments import space.kscience.kmath.geometry.Circle2D import space.kscience.kmath.geometry.Vector2D import space.kscience.kmath.geometry.circumference +import space.kscience.kmath.trajectory.ArcSegment import space.kscience.kmath.trajectory.radiansToDegrees import kotlin.test.Test import kotlin.test.assertEquals 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 afc473d79..11eaa0fb3 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 @@ -2,6 +2,7 @@ package space.kscience.kmath.trajectory.segments import space.kscience.kmath.geometry.Euclidean2DSpace import space.kscience.kmath.geometry.Vector2D +import space.kscience.kmath.trajectory.StraightSegment import space.kscience.kmath.trajectory.radiansToDegrees import kotlin.math.pow import kotlin.math.sqrt -- 2.34.1 From 0e9072710fe43a17cedf780fb22331b27fb69589 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 29 Jul 2022 15:58:02 +0300 Subject: [PATCH 165/275] Kotlin 1.7.20-Beta --- CHANGELOG.md | 1 + benchmarks/build.gradle.kts | 2 +- build.gradle.kts | 2 +- buildSrc/build.gradle.kts | 4 ++-- buildSrc/settings.gradle.kts | 2 +- .../kscience/kmath/benchmarks/addBenchmarkProperties.kt | 2 +- examples/build.gradle.kts | 2 +- gradle.properties | 2 +- kmath-ast/build.gradle.kts | 4 ++-- kmath-commons/build.gradle.kts | 4 ++-- kmath-complex/build.gradle.kts | 6 +++--- kmath-core/build.gradle.kts | 6 +++--- kmath-coroutines/build.gradle.kts | 8 ++++---- kmath-dimensions/build.gradle.kts | 6 +++--- kmath-ejml/build.gradle.kts | 4 ++-- kmath-for-real/build.gradle.kts | 6 +++--- kmath-functions/build.gradle.kts | 6 +++--- kmath-geometry/build.gradle.kts | 6 +++--- kmath-histograms/build.gradle.kts | 6 +++--- kmath-jafama/build.gradle.kts | 4 ++-- kmath-jupyter/build.gradle.kts | 4 ++-- kmath-kotlingrad/build.gradle.kts | 4 ++-- kmath-memory/build.gradle.kts | 6 +++--- kmath-multik/build.gradle.kts | 4 ++-- kmath-nd4j/build.gradle.kts | 4 ++-- kmath-optimization/build.gradle.kts | 6 +++--- kmath-polynomial/build.gradle.kts | 6 +++--- kmath-stat/build.gradle.kts | 6 +++--- kmath-symja/build.gradle.kts | 4 ++-- kmath-tensorflow/build.gradle.kts | 4 ++-- kmath-tensors/build.gradle.kts | 6 +++--- kmath-trajectory/build.gradle.kts | 6 +++--- kmath-viktor/build.gradle.kts | 4 ++-- settings.gradle.kts | 2 +- test-utils/build.gradle.kts | 4 ++-- 35 files changed, 77 insertions(+), 76 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4852f474a..66d83ec34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## [Unreleased] ### Added +- 2D optimal trajectory computation in a separate module `kmath-trajectory` - Autodiff for generic algebra elements in core! - Algebra now has an obligatory `bufferFactory` (#477). diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index 22712816d..e86990043 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -163,7 +163,7 @@ tasks.withType { } readme { - maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + maturity = space.kscience.gradle.Maturity.EXPERIMENTAL } addBenchmarkProperties() diff --git a/build.gradle.kts b/build.gradle.kts index d8c591799..c57b29105 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("ru.mipt.npm.gradle.project") + id("space.kscience.gradle.project") id("org.jetbrains.kotlinx.kover") version "0.5.0" } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 20611e92d..9bf5d03d0 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - kotlin("jvm") version "1.7.0" + kotlin("jvm") version "1.7.20-Beta" `kotlin-dsl` `version-catalog` alias(npmlibs.plugins.kotlin.plugin.serialization) @@ -19,7 +19,7 @@ val kotlinVersion = npmlibs.versions.kotlin.asProvider().get() val benchmarksVersion = npmlibs.versions.kotlinx.benchmark.get() dependencies { - api("ru.mipt.npm:gradle-tools:$toolsVersion") + api("space.kscience:gradle-tools:$toolsVersion") api(npmlibs.atomicfu.gradle) //plugins form benchmarks api("org.jetbrains.kotlinx:kotlinx-benchmark-plugin:$benchmarksVersion") diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts index bce265510..403e0f52c 100644 --- a/buildSrc/settings.gradle.kts +++ b/buildSrc/settings.gradle.kts @@ -27,7 +27,7 @@ dependencyResolutionManagement { versionCatalogs { create("npmlibs") { - from("ru.mipt.npm:version-catalog:$toolsVersion") + from("space.kscience:version-catalog:$toolsVersion") } } } diff --git a/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt index dc9327348..33d186bfc 100644 --- a/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt +++ b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt @@ -9,7 +9,7 @@ import kotlinx.benchmark.gradle.BenchmarksExtension import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json import org.gradle.api.Project -import ru.mipt.npm.gradle.KScienceReadmeExtension +import space.kscience.gradle.KScienceReadmeExtension import java.time.LocalDateTime import java.time.ZoneId import java.time.format.DateTimeFormatter diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index aa5c1f47a..cfa50815d 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -68,5 +68,5 @@ tasks.withType { } readme { - maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + maturity = space.kscience.gradle.Maturity.EXPERIMENTAL } diff --git a/gradle.properties b/gradle.properties index 6b45ee49f..ca8c91191 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,4 +12,4 @@ org.gradle.configureondemand=true org.gradle.parallel=true org.gradle.jvmargs=-Xmx4096m -toolsVersion=0.11.8-kotlin-1.7.10 +toolsVersion=0.12.0-kotlin-1.7.20-Beta diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index f49c2767a..c1333eba5 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -1,6 +1,6 @@ plugins { kotlin("multiplatform") - id("ru.mipt.npm.gradle.common") + id("space.kscience.gradle.common") } kotlin.js { @@ -61,7 +61,7 @@ if (System.getProperty("space.kscience.kmath.ast.dump.generated.classes") == "1" } readme { - maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + maturity = space.kscience.gradle.Maturity.EXPERIMENTAL propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-commons/build.gradle.kts b/kmath-commons/build.gradle.kts index 96c17a215..643307b48 100644 --- a/kmath-commons/build.gradle.kts +++ b/kmath-commons/build.gradle.kts @@ -1,6 +1,6 @@ plugins { kotlin("jvm") - id("ru.mipt.npm.gradle.common") + id("space.kscience.gradle.common") } description = "Commons math binding for kmath" @@ -16,5 +16,5 @@ dependencies { } readme { - maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + maturity = space.kscience.gradle.Maturity.EXPERIMENTAL } \ No newline at end of file diff --git a/kmath-complex/build.gradle.kts b/kmath-complex/build.gradle.kts index f0ce631a5..dbe96b153 100644 --- a/kmath-complex/build.gradle.kts +++ b/kmath-complex/build.gradle.kts @@ -1,7 +1,7 @@ plugins { kotlin("multiplatform") - id("ru.mipt.npm.gradle.common") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.common") + id("space.kscience.gradle.native") } kotlin.sourceSets { @@ -14,7 +14,7 @@ kotlin.sourceSets { readme { description = "Complex numbers and quaternions." - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = space.kscience.gradle.Maturity.PROTOTYPE propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index 052924ce8..d055b5350 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - id("ru.mipt.npm.gradle.mpp") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.mpp") + id("space.kscience.gradle.native") } kotlin.sourceSets { @@ -26,7 +26,7 @@ kotlin.sourceSets { readme { description = "Core classes, algebra definitions, basic linear algebra" - maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT + maturity = space.kscience.gradle.Maturity.DEVELOPMENT propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-coroutines/build.gradle.kts b/kmath-coroutines/build.gradle.kts index aa30c412b..104adf268 100644 --- a/kmath-coroutines/build.gradle.kts +++ b/kmath-coroutines/build.gradle.kts @@ -1,7 +1,7 @@ plugins { kotlin("multiplatform") - id("ru.mipt.npm.gradle.common") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.common") + id("space.kscience.gradle.native") } kotlin.sourceSets { @@ -17,11 +17,11 @@ kotlin.sourceSets { dependencies { api(project(":kmath-core")) api(project(":kmath-complex")) - api("org.jetbrains.kotlinx:kotlinx-coroutines-core:${ru.mipt.npm.gradle.KScienceVersions.coroutinesVersion}") + api("org.jetbrains.kotlinx:kotlinx-coroutines-core:${space.kscience.gradle.KScienceVersions.coroutinesVersion}") } } } readme { - maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + maturity = space.kscience.gradle.Maturity.EXPERIMENTAL } \ No newline at end of file diff --git a/kmath-dimensions/build.gradle.kts b/kmath-dimensions/build.gradle.kts index 885f3c227..ee1950fa8 100644 --- a/kmath-dimensions/build.gradle.kts +++ b/kmath-dimensions/build.gradle.kts @@ -1,7 +1,7 @@ plugins { kotlin("multiplatform") - id("ru.mipt.npm.gradle.common") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.common") + id("space.kscience.gradle.native") } description = "A proof of concept module for adding type-safe dimensions to structures" @@ -21,5 +21,5 @@ kotlin.sourceSets { } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = space.kscience.gradle.Maturity.PROTOTYPE } diff --git a/kmath-ejml/build.gradle.kts b/kmath-ejml/build.gradle.kts index 727d21e3a..d400d6600 100644 --- a/kmath-ejml/build.gradle.kts +++ b/kmath-ejml/build.gradle.kts @@ -2,7 +2,7 @@ import space.kscience.kmath.ejml.codegen.ejmlCodegen plugins { kotlin("jvm") - id("ru.mipt.npm.gradle.common") + id("space.kscience.gradle.common") } dependencies { @@ -14,7 +14,7 @@ dependencies { } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = space.kscience.gradle.Maturity.PROTOTYPE propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-for-real/build.gradle.kts b/kmath-for-real/build.gradle.kts index 18c2c50ad..6b6242c24 100644 --- a/kmath-for-real/build.gradle.kts +++ b/kmath-for-real/build.gradle.kts @@ -1,7 +1,7 @@ plugins { kotlin("multiplatform") - id("ru.mipt.npm.gradle.common") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.common") + id("space.kscience.gradle.native") } kotlin.sourceSets.commonMain { @@ -16,7 +16,7 @@ readme { All operations are specialized to work with `Double` numbers without declaring algebraic contexts. One can still use generic algebras though. """.trimIndent() - maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + maturity = space.kscience.gradle.Maturity.EXPERIMENTAL propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-functions/build.gradle.kts b/kmath-functions/build.gradle.kts index 337875ba4..c68102c2e 100644 --- a/kmath-functions/build.gradle.kts +++ b/kmath-functions/build.gradle.kts @@ -1,7 +1,7 @@ plugins { kotlin("multiplatform") - id("ru.mipt.npm.gradle.common") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.common") + id("space.kscience.gradle.native") } description = "Functions, integration and interpolation" @@ -19,7 +19,7 @@ dependencies { } readme { - maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + maturity = space.kscience.gradle.Maturity.EXPERIMENTAL propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature("piecewise", "src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt") { diff --git a/kmath-geometry/build.gradle.kts b/kmath-geometry/build.gradle.kts index bfe2e32a2..c9d8823bc 100644 --- a/kmath-geometry/build.gradle.kts +++ b/kmath-geometry/build.gradle.kts @@ -1,7 +1,7 @@ plugins { kotlin("multiplatform") - id("ru.mipt.npm.gradle.common") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.common") + id("space.kscience.gradle.native") } kotlin.sourceSets.commonMain { @@ -11,5 +11,5 @@ kotlin.sourceSets.commonMain { } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = space.kscience.gradle.Maturity.PROTOTYPE } diff --git a/kmath-histograms/build.gradle.kts b/kmath-histograms/build.gradle.kts index 786086c9f..94d1f5fb7 100644 --- a/kmath-histograms/build.gradle.kts +++ b/kmath-histograms/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - id("ru.mipt.npm.gradle.mpp") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.mpp") + id("space.kscience.gradle.native") } //apply(plugin = "kotlinx-atomicfu") @@ -22,5 +22,5 @@ kotlin.sourceSets { } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = space.kscience.gradle.Maturity.PROTOTYPE } diff --git a/kmath-jafama/build.gradle.kts b/kmath-jafama/build.gradle.kts index 925a2bc60..da77f469d 100644 --- a/kmath-jafama/build.gradle.kts +++ b/kmath-jafama/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("ru.mipt.npm.gradle.jvm") + id("space.kscience.gradle.jvm") } description = "Jafama integration module" @@ -14,7 +14,7 @@ repositories { } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = space.kscience.gradle.Maturity.PROTOTYPE propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature("jafama-double", "src/main/kotlin/space/kscience/kmath/jafama/") { diff --git a/kmath-jupyter/build.gradle.kts b/kmath-jupyter/build.gradle.kts index ca1a5485f..d92b6ca0d 100644 --- a/kmath-jupyter/build.gradle.kts +++ b/kmath-jupyter/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("ru.mipt.npm.gradle.jvm") + id("space.kscience.gradle.jvm") kotlin("jupyter.api") } @@ -14,7 +14,7 @@ kscience { } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = space.kscience.gradle.Maturity.PROTOTYPE } kotlin.sourceSets.all { diff --git a/kmath-kotlingrad/build.gradle.kts b/kmath-kotlingrad/build.gradle.kts index 2f6d41bbb..a7f4ee37f 100644 --- a/kmath-kotlingrad/build.gradle.kts +++ b/kmath-kotlingrad/build.gradle.kts @@ -1,6 +1,6 @@ plugins { kotlin("jvm") - id("ru.mipt.npm.gradle.common") + id("space.kscience.gradle.common") } kotlin.sourceSets @@ -18,7 +18,7 @@ dependencies { } readme { - maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + maturity = space.kscience.gradle.Maturity.EXPERIMENTAL propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-memory/build.gradle.kts b/kmath-memory/build.gradle.kts index 2bd6dd723..55a7ff6aa 100644 --- a/kmath-memory/build.gradle.kts +++ b/kmath-memory/build.gradle.kts @@ -1,10 +1,10 @@ plugins { - id("ru.mipt.npm.gradle.mpp") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.mpp") + id("space.kscience.gradle.native") } readme { - maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT + maturity = space.kscience.gradle.Maturity.DEVELOPMENT description = """ An API and basic implementation for arranging objects in a continuous memory block. """.trimIndent() diff --git a/kmath-multik/build.gradle.kts b/kmath-multik/build.gradle.kts index df2292f2e..0f31a183a 100644 --- a/kmath-multik/build.gradle.kts +++ b/kmath-multik/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("ru.mipt.npm.gradle.jvm") + id("space.kscience.gradle.jvm") } description = "JetBrains Multik connector" @@ -10,5 +10,5 @@ dependencies { } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = space.kscience.gradle.Maturity.PROTOTYPE } \ No newline at end of file diff --git a/kmath-nd4j/build.gradle.kts b/kmath-nd4j/build.gradle.kts index 09264501f..11af7d6dc 100644 --- a/kmath-nd4j/build.gradle.kts +++ b/kmath-nd4j/build.gradle.kts @@ -1,6 +1,6 @@ plugins { kotlin("jvm") - id("ru.mipt.npm.gradle.common") + id("space.kscience.gradle.common") } description = "ND4J NDStructure implementation and according NDAlgebra classes" @@ -13,7 +13,7 @@ dependencies { } readme { - maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + maturity = space.kscience.gradle.Maturity.EXPERIMENTAL propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature(id = "nd4jarraystructure") { "NDStructure wrapper for INDArray" } feature(id = "nd4jarrayrings") { "Rings over Nd4jArrayStructure of Int and Long" } diff --git a/kmath-optimization/build.gradle.kts b/kmath-optimization/build.gradle.kts index 2e5bf6005..53f379830 100644 --- a/kmath-optimization/build.gradle.kts +++ b/kmath-optimization/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - id("ru.mipt.npm.gradle.mpp") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.mpp") + id("space.kscience.gradle.native") } kotlin.sourceSets { @@ -17,5 +17,5 @@ kotlin.sourceSets { } readme { - maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + maturity = space.kscience.gradle.Maturity.EXPERIMENTAL } diff --git a/kmath-polynomial/build.gradle.kts b/kmath-polynomial/build.gradle.kts index 5e66f83ec..42b90a70e 100644 --- a/kmath-polynomial/build.gradle.kts +++ b/kmath-polynomial/build.gradle.kts @@ -1,7 +1,7 @@ plugins { kotlin("multiplatform") - id("ru.mipt.npm.gradle.common") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.common") + id("space.kscience.gradle.native") } description = "Polynomials, rational functions, and utilities" @@ -19,7 +19,7 @@ dependencies { } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = space.kscience.gradle.Maturity.PROTOTYPE propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature("polynomial abstraction", "src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt") { diff --git a/kmath-stat/build.gradle.kts b/kmath-stat/build.gradle.kts index b458135b3..1d1831047 100644 --- a/kmath-stat/build.gradle.kts +++ b/kmath-stat/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - id("ru.mipt.npm.gradle.mpp") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.mpp") + id("space.kscience.gradle.native") } kotlin.sourceSets { @@ -20,5 +20,5 @@ kotlin.sourceSets { } readme { - maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL + maturity = space.kscience.gradle.Maturity.EXPERIMENTAL } \ No newline at end of file diff --git a/kmath-symja/build.gradle.kts b/kmath-symja/build.gradle.kts index 65c329d52..1984236ca 100644 --- a/kmath-symja/build.gradle.kts +++ b/kmath-symja/build.gradle.kts @@ -5,7 +5,7 @@ plugins { kotlin("jvm") - id("ru.mipt.npm.gradle.common") + id("space.kscience.gradle.common") } description = "Symja integration module" @@ -38,5 +38,5 @@ dependencies { } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = space.kscience.gradle.Maturity.PROTOTYPE } diff --git a/kmath-tensorflow/build.gradle.kts b/kmath-tensorflow/build.gradle.kts index 9380a7308..1e4ba12da 100644 --- a/kmath-tensorflow/build.gradle.kts +++ b/kmath-tensorflow/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("ru.mipt.npm.gradle.jvm") + id("space.kscience.gradle.jvm") } description = "Google tensorflow connector" @@ -11,5 +11,5 @@ dependencies { } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = space.kscience.gradle.Maturity.PROTOTYPE } \ No newline at end of file diff --git a/kmath-tensors/build.gradle.kts b/kmath-tensors/build.gradle.kts index 66316d21d..b2a4c36bd 100644 --- a/kmath-tensors/build.gradle.kts +++ b/kmath-tensors/build.gradle.kts @@ -1,7 +1,7 @@ plugins { kotlin("multiplatform") - id("ru.mipt.npm.gradle.common") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.common") + id("space.kscience.gradle.native") } kotlin.sourceSets { @@ -22,7 +22,7 @@ kotlin.sourceSets { } readme { - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = space.kscience.gradle.Maturity.PROTOTYPE propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) feature( diff --git a/kmath-trajectory/build.gradle.kts b/kmath-trajectory/build.gradle.kts index db80be02a..f4dba25ab 100644 --- a/kmath-trajectory/build.gradle.kts +++ b/kmath-trajectory/build.gradle.kts @@ -1,7 +1,7 @@ plugins { kotlin("multiplatform") - id("ru.mipt.npm.gradle.common") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.common") + id("space.kscience.gradle.native") } kotlin.sourceSets.commonMain { @@ -12,6 +12,6 @@ kotlin.sourceSets.commonMain { readme { description = "Path and trajectory optimization" - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE + maturity = space.kscience.gradle.Maturity.PROTOTYPE propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) } diff --git a/kmath-viktor/build.gradle.kts b/kmath-viktor/build.gradle.kts index 2e932b441..1b22e9c38 100644 --- a/kmath-viktor/build.gradle.kts +++ b/kmath-viktor/build.gradle.kts @@ -1,6 +1,6 @@ plugins { kotlin("jvm") - id("ru.mipt.npm.gradle.common") + id("space.kscience.gradle.common") } description = "Binding for https://github.com/JetBrains-Research/viktor" @@ -11,5 +11,5 @@ dependencies { } readme { - maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT + maturity = space.kscience.gradle.Maturity.DEVELOPMENT } diff --git a/settings.gradle.kts b/settings.gradle.kts index 829e59144..f53232f44 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -14,7 +14,7 @@ dependencyResolutionManagement { versionCatalogs { create("npmlibs") { - from("ru.mipt.npm:version-catalog:$toolsVersion") + from("space.kscience:version-catalog:$toolsVersion") } } } diff --git a/test-utils/build.gradle.kts b/test-utils/build.gradle.kts index 88c7ea9d0..49c4758e3 100644 --- a/test-utils/build.gradle.kts +++ b/test-utils/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - id("ru.mipt.npm.gradle.mpp") - id("ru.mipt.npm.gradle.native") + id("space.kscience.gradle.mpp") + id("space.kscience.gradle.native") } kotlin.sourceSets { -- 2.34.1 From 94562179354d5cf86d5894826ebee0afa88ca771 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 3 Aug 2022 17:29:01 +0300 Subject: [PATCH 166/275] Update multik algebra --- gradle.properties | 2 +- kmath-multik/build.gradle.kts | 2 +- .../kmath/multik/MultikDoubleAlgebra.kt | 4 + .../kmath/multik/MultikFloatAlgebra.kt | 22 ++++ .../kscience/kmath/multik/MultikIntAlgebra.kt | 20 ++++ .../kmath/multik/MultikLongAlgebra.kt | 22 ++++ .../kmath/multik/MultikShortAlgebra.kt | 20 ++++ .../kscience/kmath/multik/MultikTensor.kt | 40 +++++++ .../kmath/multik/MultikTensorAlgebra.kt | 102 +++++------------- 9 files changed, 154 insertions(+), 80 deletions(-) create mode 100644 kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikFloatAlgebra.kt create mode 100644 kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikIntAlgebra.kt create mode 100644 kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikLongAlgebra.kt create mode 100644 kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikShortAlgebra.kt create mode 100644 kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikTensor.kt diff --git a/gradle.properties b/gradle.properties index ca8c91191..b3e3f4cda 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ kotlin.code.style=official kotlin.jupyter.add.scanner=false kotlin.mpp.stability.nowarn=true kotlin.native.ignoreDisabledTargets=true -//kotlin.incremental.js.ir=true +kotlin.incremental.js.ir=true org.gradle.configureondemand=true org.gradle.parallel=true diff --git a/kmath-multik/build.gradle.kts b/kmath-multik/build.gradle.kts index 0f31a183a..ee31ead3c 100644 --- a/kmath-multik/build.gradle.kts +++ b/kmath-multik/build.gradle.kts @@ -6,7 +6,7 @@ description = "JetBrains Multik connector" dependencies { api(project(":kmath-tensors")) - api("org.jetbrains.kotlinx:multik-default:0.1.0") + api("org.jetbrains.kotlinx:multik-default:0.2.0") } readme { diff --git a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt b/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt index 0de2d8349..1d4665618 100644 --- a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt +++ b/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt @@ -5,6 +5,8 @@ package space.kscience.kmath.multik +import org.jetbrains.kotlinx.multik.api.Multik +import org.jetbrains.kotlinx.multik.api.ndarrayOf import org.jetbrains.kotlinx.multik.ndarray.data.DataType import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.StructureND @@ -54,6 +56,8 @@ public object MultikDoubleAlgebra : MultikDivisionTensorAlgebra): MultikTensor = arg.map { atanh(it) } + + override fun scalar(value: Double): MultikTensor = Multik.ndarrayOf(value).wrap() } public val Double.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikDoubleAlgebra diff --git a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikFloatAlgebra.kt b/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikFloatAlgebra.kt new file mode 100644 index 000000000..8dd9b3f60 --- /dev/null +++ b/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikFloatAlgebra.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.multik + +import org.jetbrains.kotlinx.multik.api.Multik +import org.jetbrains.kotlinx.multik.api.ndarrayOf +import org.jetbrains.kotlinx.multik.ndarray.data.DataType +import space.kscience.kmath.operations.FloatField + +public object MultikFloatAlgebra : MultikDivisionTensorAlgebra() { + override val elementAlgebra: FloatField get() = FloatField + override val type: DataType get() = DataType.FloatDataType + + override fun scalar(value: Float): MultikTensor = Multik.ndarrayOf(value).wrap() +} + + +public val Float.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikFloatAlgebra +public val FloatField.multikAlgebra: MultikTensorAlgebra get() = MultikFloatAlgebra \ No newline at end of file diff --git a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikIntAlgebra.kt b/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikIntAlgebra.kt new file mode 100644 index 000000000..b9e0125e8 --- /dev/null +++ b/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikIntAlgebra.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.multik + +import org.jetbrains.kotlinx.multik.api.Multik +import org.jetbrains.kotlinx.multik.api.ndarrayOf +import org.jetbrains.kotlinx.multik.ndarray.data.DataType +import space.kscience.kmath.operations.IntRing + +public object MultikIntAlgebra : MultikTensorAlgebra() { + override val elementAlgebra: IntRing get() = IntRing + override val type: DataType get() = DataType.IntDataType + override fun scalar(value: Int): MultikTensor = Multik.ndarrayOf(value).wrap() +} + +public val Int.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikIntAlgebra +public val IntRing.multikAlgebra: MultikTensorAlgebra get() = MultikIntAlgebra \ No newline at end of file diff --git a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikLongAlgebra.kt b/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikLongAlgebra.kt new file mode 100644 index 000000000..1f3dfb0e5 --- /dev/null +++ b/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikLongAlgebra.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.multik + +import org.jetbrains.kotlinx.multik.api.Multik +import org.jetbrains.kotlinx.multik.api.ndarrayOf +import org.jetbrains.kotlinx.multik.ndarray.data.DataType +import space.kscience.kmath.operations.LongRing + +public object MultikLongAlgebra : MultikTensorAlgebra() { + override val elementAlgebra: LongRing get() = LongRing + override val type: DataType get() = DataType.LongDataType + + override fun scalar(value: Long): MultikTensor = Multik.ndarrayOf(value).wrap() +} + + +public val Long.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikLongAlgebra +public val LongRing.multikAlgebra: MultikTensorAlgebra get() = MultikLongAlgebra \ No newline at end of file diff --git a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikShortAlgebra.kt b/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikShortAlgebra.kt new file mode 100644 index 000000000..b9746571d --- /dev/null +++ b/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikShortAlgebra.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.multik + +import org.jetbrains.kotlinx.multik.api.Multik +import org.jetbrains.kotlinx.multik.api.ndarrayOf +import org.jetbrains.kotlinx.multik.ndarray.data.DataType +import space.kscience.kmath.operations.ShortRing + +public object MultikShortAlgebra : MultikTensorAlgebra() { + override val elementAlgebra: ShortRing get() = ShortRing + override val type: DataType get() = DataType.ShortDataType + override fun scalar(value: Short): MultikTensor = Multik.ndarrayOf(value).wrap() +} + +public val Short.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikShortAlgebra +public val ShortRing.multikAlgebra: MultikTensorAlgebra get() = MultikShortAlgebra \ No newline at end of file diff --git a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikTensor.kt b/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikTensor.kt new file mode 100644 index 000000000..7efe672b4 --- /dev/null +++ b/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikTensor.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.multik + +import org.jetbrains.kotlinx.multik.ndarray.data.* +import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.nd.Shape +import space.kscience.kmath.tensors.api.Tensor + +@JvmInline +public value class MultikTensor(public val array: MutableMultiArray) : Tensor { + override val shape: Shape get() = array.shape + + override fun get(index: IntArray): T = array[index] + + @PerformancePitfall + override fun elements(): Sequence> = + array.multiIndices.iterator().asSequence().map { it to get(it) } + + override fun set(index: IntArray, value: T) { + array[index] = value + } +} + + +internal fun MultiArray.asD1Array(): D1Array { + if (this is NDArray) + return this.asD1Array() + else throw ClassCastException("Cannot cast MultiArray to NDArray.") +} + + +internal fun MultiArray.asD2Array(): D2Array { + if (this is NDArray) + return this.asD2Array() + else throw ClassCastException("Cannot cast MultiArray to NDArray.") +} \ No newline at end of file diff --git a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt b/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt index 250ef7e7f..1cc1b9b6d 100644 --- a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt +++ b/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt @@ -10,46 +10,16 @@ package space.kscience.kmath.multik import org.jetbrains.kotlinx.multik.api.* import org.jetbrains.kotlinx.multik.api.linalg.LinAlg import org.jetbrains.kotlinx.multik.api.math.Math +import org.jetbrains.kotlinx.multik.api.stat.Statistics import org.jetbrains.kotlinx.multik.ndarray.data.* import org.jetbrains.kotlinx.multik.ndarray.operations.* import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.nd.DefaultStrides -import space.kscience.kmath.nd.Shape -import space.kscience.kmath.nd.StructureND -import space.kscience.kmath.nd.mapInPlace +import space.kscience.kmath.nd.* import space.kscience.kmath.operations.* import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.api.TensorAlgebra import space.kscience.kmath.tensors.api.TensorPartialDivisionAlgebra -@JvmInline -public value class MultikTensor(public val array: MutableMultiArray) : Tensor { - override val shape: Shape get() = array.shape - - override fun get(index: IntArray): T = array[index] - - @PerformancePitfall - override fun elements(): Sequence> = - array.multiIndices.iterator().asSequence().map { it to get(it) } - - override fun set(index: IntArray, value: T) { - array[index] = value - } -} - -private fun MultiArray.asD1Array(): D1Array { - if (this is NDArray) - return this.asD1Array() - else throw ClassCastException("Cannot cast MultiArray to NDArray.") -} - - -private fun MultiArray.asD2Array(): D2Array { - if (this is NDArray) - return this.asD2Array() - else throw ClassCastException("Cannot cast MultiArray to NDArray.") -} - public abstract class MultikTensorAlgebra> : TensorAlgebra where T : Number, T : Comparable { @@ -59,7 +29,6 @@ public abstract class MultikTensorAlgebra> : TensorAlgebra protected val multikLinAl: LinAlg = mk.linalg protected val multikStat: Statistics = mk.stat - override fun structureND(shape: Shape, initializer: A.(IntArray) -> T): MultikTensor { val strides = DefaultStrides(shape) val memoryView = initMemoryView(strides.linearSize, type) @@ -240,11 +209,15 @@ public abstract class MultikTensorAlgebra> : TensorAlgebra override fun Tensor.viewAs(other: StructureND): MultikTensor = view(other.shape) + public abstract fun scalar(value: T): MultikTensor + override fun StructureND.dot(other: StructureND): MultikTensor = if (this.shape.size == 1 && other.shape.size == 1) { - Multik.ndarrayOf( - multikLinAl.linAlgEx.dotVV(asMultik().array.asD1Array(), other.asMultik().array.asD1Array()) - ).wrap() + scalar( + multikLinAl.linAlgEx.dotVV( + asMultik().array.asD1Array(), other.asMultik().array.asD1Array() + ) + ) } else if (this.shape.size == 2 && other.shape.size == 2) { multikLinAl.linAlgEx.dotMM(asMultik().array.asD2Array(), other.asMultik().array.asD2Array()).wrap() } else if (this.shape.size == 2 && other.shape.size == 1) { @@ -254,41 +227,46 @@ public abstract class MultikTensorAlgebra> : TensorAlgebra } override fun diagonalEmbedding(diagonalEntries: Tensor, offset: Int, dim1: Int, dim2: Int): MultikTensor { + TODO("Diagonal embedding not implemented") } - override fun StructureND.sum(): T = asMultik().array.reduceMultiIndexed { _: IntArray, acc: T, t: T -> - elementAlgebra.add(acc, t) - } + override fun StructureND.sum(): T = multikMath.sum(asMultik().array) override fun StructureND.sum(dim: Int, keepDim: Boolean): MultikTensor { - TODO("Not yet implemented") + if (keepDim) TODO("keepDim not implemented") + return multikMath.sumDN(asMultik().array, dim).wrap() } override fun StructureND.min(): T? = asMultik().array.min() override fun StructureND.min(dim: Int, keepDim: Boolean): Tensor { - TODO("Not yet implemented") + if (keepDim) TODO("keepDim not implemented") + return multikMath.minDN(asMultik().array, dim).wrap() } override fun StructureND.max(): T? = asMultik().array.max() override fun StructureND.max(dim: Int, keepDim: Boolean): Tensor { - TODO("Not yet implemented") + if (keepDim) TODO("keepDim not implemented") + return multikMath.maxDN(asMultik().array, dim).wrap() } override fun StructureND.argMax(dim: Int, keepDim: Boolean): Tensor { - TODO("Not yet implemented") + if (keepDim) TODO("keepDim not implemented") + val res = multikMath.argMaxDN(asMultik().array, dim) + return with(MultikIntAlgebra) { res.wrap() } } } public abstract class MultikDivisionTensorAlgebra> : MultikTensorAlgebra(), TensorPartialDivisionAlgebra where T : Number, T : Comparable { - override fun T.div(arg: StructureND): MultikTensor = arg.map { elementAlgebra.divide(this@div, it) } + override fun T.div(arg: StructureND): MultikTensor = + Multik.ones(arg.shape, type).apply { divAssign(arg.asMultik().array) }.wrap() override fun StructureND.div(arg: T): MultikTensor = - asMultik().array.deepCopy().apply { divAssign(arg) }.wrap() + asMultik().array.div(arg).wrap() override fun StructureND.div(arg: StructureND): MultikTensor = asMultik().array.div(arg.asMultik().array).wrap() @@ -308,36 +286,4 @@ public abstract class MultikDivisionTensorAlgebra> mapInPlace { index, t -> elementAlgebra.divide(t, arg[index]) } } } -} - -public object MultikFloatAlgebra : MultikDivisionTensorAlgebra() { - override val elementAlgebra: FloatField get() = FloatField - override val type: DataType get() = DataType.FloatDataType -} - -public val Float.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikFloatAlgebra -public val FloatField.multikAlgebra: MultikTensorAlgebra get() = MultikFloatAlgebra - -public object MultikShortAlgebra : MultikTensorAlgebra() { - override val elementAlgebra: ShortRing get() = ShortRing - override val type: DataType get() = DataType.ShortDataType -} - -public val Short.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikShortAlgebra -public val ShortRing.multikAlgebra: MultikTensorAlgebra get() = MultikShortAlgebra - -public object MultikIntAlgebra : MultikTensorAlgebra() { - override val elementAlgebra: IntRing get() = IntRing - override val type: DataType get() = DataType.IntDataType -} - -public val Int.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikIntAlgebra -public val IntRing.multikAlgebra: MultikTensorAlgebra get() = MultikIntAlgebra - -public object MultikLongAlgebra : MultikTensorAlgebra() { - override val elementAlgebra: LongRing get() = LongRing - override val type: DataType get() = DataType.LongDataType -} - -public val Long.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikLongAlgebra -public val LongRing.multikAlgebra: MultikTensorAlgebra get() = MultikLongAlgebra \ No newline at end of file +} \ No newline at end of file -- 2.34.1 From 5402ba47c90be0f24f4642dd78adb5ed208c4c08 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 3 Aug 2022 18:10:44 +0300 Subject: [PATCH 167/275] Restrict tensor dot ot vectors and matrices only. Introduce bdot to Double TensorAlgebra for broadcasting operations. --- CHANGELOG.md | 3 +- .../kmath/tensors/api/TensorAlgebra.kt | 11 +---- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 46 +++++++++++++++++-- .../core/TestDoubleLinearOpsAlgebra.kt | 12 ++--- .../tensors/core/TestDoubleTensorAlgebra.kt | 4 +- 5 files changed, 52 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66d83ec34..03fb4cf8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,9 @@ - Algebra now has an obligatory `bufferFactory` (#477). ### Changed -- Kotlin 1.7 +- Kotlin 1.7.20 - `LazyStructure` `deffered` -> `async` to comply with coroutines code style +- Default `dot` operation in tensor algebra no longer support broadcasting. Instead `bdot` operation is added to `DoubleTensorAlgebra`. ### Deprecated diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index 86d4eaa4e..1b11dc54f 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 @@ -213,16 +213,7 @@ public interface TensorAlgebra> : RingOpsND { * 4. If the first argument is 2-dimensional and the second argument is 1-dimensional, * the matrix-vector product is returned. * - * 5. If both arguments are at least 1-dimensional and at least one argument is N-dimensional (where N > 2), - * then a batched matrix multiply is returned. If the first argument is 1-dimensional, - * a 1 is prepended to its dimension for the purpose of the batched matrix multiply and removed after. - * If the second argument is 1-dimensional, a 1 is appended to its dimension for the purpose of the batched matrix - * multiple and removed after. - * The non-matrix (i.e., batch) dimensions are broadcast (and thus must be broadcastable). - * For example, if `input` is a (j × 1 × n × n) tensor and `other` is a - * (k × n × n) tensor, out will be a (j × k × n × n) tensor. - * - * For more information: https://pytorch.org/docs/stable/generated/torch.matmul.html + * Otherwise, throw an exception. * * @param other tensor to be multiplied. * @return a mathematical product of two tensors. diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index e9dc34748..af4150f5b 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 @@ -381,7 +381,36 @@ public open class DoubleTensorAlgebra : override fun Tensor.viewAs(other: StructureND): DoubleTensor = tensor.view(other.shape) - override infix fun StructureND.dot(other: StructureND): DoubleTensor { + /** + * Broadcasting Matrix product of two tensors. + * + * The behavior depends on the dimensionality of the tensors as follows: + * 1. If both tensors are 1-dimensional, the dot product (scalar) is returned. + * + * 2. If both arguments are 2-dimensional, the matrix-matrix product is returned. + * + * 3. If the first argument is 1-dimensional and the second argument is 2-dimensional, + * a 1 is prepended to its dimension for the purpose of the matrix multiply. + * After the matrix multiply, depending on the implementation the prepended dimension might be removed. + * + * 4. If the first argument is 2-dimensional and the second argument is 1-dimensional, + * the matrix-vector product is returned. + * + * 5. If both arguments are at least 1-dimensional and at least one argument is N-dimensional (where N > 2), + * then a batched matrix multiply is returned. If the first argument is 1-dimensional, + * a 1 is prepended to its dimension for the purpose of the batched matrix multiply and removed after. + * If the second argument is 1-dimensional, a 1 is appended to its dimension for the purpose of the batched matrix + * multiple and removed after. + * The non-matrix (i.e., batch) dimensions are broadcast (and thus must be broadcastable). + * For example, if `input` is a (j × 1 × n × n) tensor and `other` is a + * (k × n × n) tensor, out will be a (j × k × n × n) tensor. + * + * For more information: https://pytorch.org/docs/stable/generated/torch.matmul.html + * + * @param other tensor to be multiplied. + * @return a mathematical product of two tensors. + */ + public infix fun StructureND.bdot(other: StructureND): DoubleTensor { if (tensor.shape.size == 1 && other.shape.size == 1) { return DoubleTensor(intArrayOf(1), doubleArrayOf(tensor.times(other).tensor.mutableBuffer.array().sum())) } @@ -430,6 +459,11 @@ public open class DoubleTensorAlgebra : } } + override fun StructureND.dot(other: StructureND): DoubleTensor { + return if (dimension in 0..2 && other.dimension in 0..2) bdot(other) + else error("Only vectors and matrices are allowed in non-broadcasting dot operation") + } + override fun diagonalEmbedding( diagonalEntries: Tensor, offset: Int, @@ -587,7 +621,8 @@ public open class DoubleTensorAlgebra : val resNumElements = resShape.reduce(Int::times) val init = foldFunction(DoubleArray(1) { 0.0 }) val resTensor = BufferedTensor(resShape, - MutableBuffer.auto(resNumElements) { init }, 0) + MutableBuffer.auto(resNumElements) { init }, 0 + ) for (index in resTensor.indices) { val prefix = index.take(dim).toIntArray() val suffix = index.takeLast(dimension - dim - 1).toIntArray() @@ -882,7 +917,8 @@ public open class DoubleTensorAlgebra : return Triple(uTensor.transpose(), sTensor, vTensor.transpose()) } - override fun StructureND.symEig(): Pair = symEigJacobi(maxIteration = 50, epsilon = 1e-15) + override fun StructureND.symEig(): Pair = + symEigJacobi(maxIteration = 50, epsilon = 1e-15) /** * Returns eigenvalues and eigenvectors of a real symmetric matrix input or a batch of real symmetric matrices, @@ -909,7 +945,7 @@ public open class DoubleTensorAlgebra : val (u, s, v) = tensor.svd(epsilon) val shp = s.shape + intArrayOf(1) - val utv = u.transpose() dot v + val utv = u.transpose() bdot v val n = s.shape.last() for (matrix in utv.matrixSequence()) { matrix.as2D().cleanSym(n) @@ -951,7 +987,7 @@ public open class DoubleTensorAlgebra : private fun MutableStructure2D.jacobiHelper( maxIteration: Int, - epsilon: Double + epsilon: Double, ): Pair, Structure2D> { val n = this.shape[0] val A_ = this.copy() diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index e025d4b71..6ae7ae8ef 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 @@ -115,7 +115,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { assertTrue { q.shape contentEquals shape } assertTrue { r.shape contentEquals shape } - assertTrue((q dot r).eq(tensor)) + assertTrue((q bdot r).eq(tensor)) } @@ -136,17 +136,17 @@ internal class TestDoubleLinearOpsTensorAlgebra { assertTrue { l.shape contentEquals shape } assertTrue { u.shape contentEquals shape } - assertTrue((p dot tensor).eq(l dot u)) + assertTrue((p bdot tensor).eq(l bdot u)) } @Test fun testCholesky() = DoubleTensorAlgebra { val tensor = randomNormal(intArrayOf(2, 5, 5), 0) - val sigma = (tensor dot tensor.transpose()) + diagonalEmbedding( + val sigma = (tensor bdot tensor.transpose()) + diagonalEmbedding( fromArray(intArrayOf(2, 5), DoubleArray(10) { 0.1 }) ) val low = sigma.cholesky() - val sigmChol = low dot low.transpose() + val sigmChol = low bdot low.transpose() assertTrue(sigma.eq(sigmChol)) } @@ -171,7 +171,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { fun testBatchedSVD() = DoubleTensorAlgebra { val tensor = randomNormal(intArrayOf(2, 5, 3), 0) val (tensorU, tensorS, tensorV) = tensor.svd() - val tensorSVD = tensorU dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) + val tensorSVD = tensorU bdot (diagonalEmbedding(tensorS) bdot tensorV.transpose()) assertTrue(tensor.eq(tensorSVD)) } @@ -180,7 +180,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { val tensor = randomNormal(shape = intArrayOf(2, 3, 3), 0) val tensorSigma = tensor + tensor.transpose() val (tensorS, tensorV) = tensorSigma.symEig() - val tensorSigmaCalc = tensorV dot (diagonalEmbedding(tensorS) dot tensorV.transpose()) + val tensorSigmaCalc = tensorV bdot (diagonalEmbedding(tensorS) bdot tensorV.transpose()) assertTrue(tensorSigma.eq(tensorSigmaCalc)) } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index 205ae2fee..2f3c8e2de 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 @@ -114,7 +114,7 @@ internal class TestDoubleTensorAlgebra { assertTrue(res12.mutableBuffer.array() contentEquals doubleArrayOf(140.0, 320.0)) assertTrue(res12.shape contentEquals intArrayOf(2)) - val res32 = tensor3.dot(tensor2) + val res32 = tensor3.bdot(tensor2) assertTrue(res32.mutableBuffer.array() contentEquals doubleArrayOf(-140.0)) assertTrue(res32.shape contentEquals intArrayOf(1, 1)) @@ -126,7 +126,7 @@ internal class TestDoubleTensorAlgebra { assertTrue(res11.mutableBuffer.array() contentEquals doubleArrayOf(22.0, 28.0, 49.0, 64.0)) assertTrue(res11.shape contentEquals intArrayOf(2, 2)) - val res45 = tensor4.dot(tensor5) + val res45 = tensor4.bdot(tensor5) assertTrue(res45.mutableBuffer.array() contentEquals doubleArrayOf( 36.0, 42.0, 48.0, 81.0, 96.0, 111.0, 126.0, 150.0, 174.0, 468.0, 501.0, 534.0, 594.0, 636.0, 678.0, 720.0, 771.0, 822.0 -- 2.34.1 From ee0d44e12e557b9b997b180ccfdb50d61bb90051 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 3 Aug 2022 18:20:46 +0300 Subject: [PATCH 168/275] rename bdot to matmul --- CHANGELOG.md | 2 +- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 8 +++++--- .../kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt | 12 ++++++------ .../kmath/tensors/core/TestDoubleTensorAlgebra.kt | 4 ++-- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 03fb4cf8c..f5ed80597 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ ### Changed - Kotlin 1.7.20 - `LazyStructure` `deffered` -> `async` to comply with coroutines code style -- Default `dot` operation in tensor algebra no longer support broadcasting. Instead `bdot` operation is added to `DoubleTensorAlgebra`. +- Default `dot` operation in tensor algebra no longer support broadcasting. Instead `matmul` operation is added to `DoubleTensorAlgebra`. ### Deprecated 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 af4150f5b..63193fe4c 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 @@ -9,6 +9,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.operations.DoubleField import space.kscience.kmath.structures.MutableBuffer @@ -410,7 +411,8 @@ public open class DoubleTensorAlgebra : * @param other tensor to be multiplied. * @return a mathematical product of two tensors. */ - public infix fun StructureND.bdot(other: StructureND): DoubleTensor { + @UnstableKMathAPI + public infix fun StructureND.matmul(other: StructureND): DoubleTensor { if (tensor.shape.size == 1 && other.shape.size == 1) { return DoubleTensor(intArrayOf(1), doubleArrayOf(tensor.times(other).tensor.mutableBuffer.array().sum())) } @@ -460,7 +462,7 @@ public open class DoubleTensorAlgebra : } override fun StructureND.dot(other: StructureND): DoubleTensor { - return if (dimension in 0..2 && other.dimension in 0..2) bdot(other) + return if (dimension in 0..2 && other.dimension in 0..2) matmul(other) else error("Only vectors and matrices are allowed in non-broadcasting dot operation") } @@ -945,7 +947,7 @@ public open class DoubleTensorAlgebra : val (u, s, v) = tensor.svd(epsilon) val shp = s.shape + intArrayOf(1) - val utv = u.transpose() bdot v + val utv = u.transpose() matmul v val n = s.shape.last() for (matrix in utv.matrixSequence()) { matrix.as2D().cleanSym(n) 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 6ae7ae8ef..98ee9e3cb 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 @@ -115,7 +115,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { assertTrue { q.shape contentEquals shape } assertTrue { r.shape contentEquals shape } - assertTrue((q bdot r).eq(tensor)) + assertTrue((q matmul r).eq(tensor)) } @@ -136,17 +136,17 @@ internal class TestDoubleLinearOpsTensorAlgebra { assertTrue { l.shape contentEquals shape } assertTrue { u.shape contentEquals shape } - assertTrue((p bdot tensor).eq(l bdot u)) + assertTrue((p matmul tensor).eq(l matmul u)) } @Test fun testCholesky() = DoubleTensorAlgebra { val tensor = randomNormal(intArrayOf(2, 5, 5), 0) - val sigma = (tensor bdot tensor.transpose()) + diagonalEmbedding( + val sigma = (tensor matmul tensor.transpose()) + diagonalEmbedding( fromArray(intArrayOf(2, 5), DoubleArray(10) { 0.1 }) ) val low = sigma.cholesky() - val sigmChol = low bdot low.transpose() + val sigmChol = low matmul low.transpose() assertTrue(sigma.eq(sigmChol)) } @@ -171,7 +171,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { fun testBatchedSVD() = DoubleTensorAlgebra { val tensor = randomNormal(intArrayOf(2, 5, 3), 0) val (tensorU, tensorS, tensorV) = tensor.svd() - val tensorSVD = tensorU bdot (diagonalEmbedding(tensorS) bdot tensorV.transpose()) + val tensorSVD = tensorU matmul (diagonalEmbedding(tensorS) matmul tensorV.transpose()) assertTrue(tensor.eq(tensorSVD)) } @@ -180,7 +180,7 @@ internal class TestDoubleLinearOpsTensorAlgebra { val tensor = randomNormal(shape = intArrayOf(2, 3, 3), 0) val tensorSigma = tensor + tensor.transpose() val (tensorS, tensorV) = tensorSigma.symEig() - val tensorSigmaCalc = tensorV bdot (diagonalEmbedding(tensorS) bdot tensorV.transpose()) + val tensorSigmaCalc = tensorV matmul (diagonalEmbedding(tensorS) matmul tensorV.transpose()) assertTrue(tensorSigma.eq(tensorSigmaCalc)) } 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 2f3c8e2de..bca6e65d0 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 @@ -114,7 +114,7 @@ internal class TestDoubleTensorAlgebra { assertTrue(res12.mutableBuffer.array() contentEquals doubleArrayOf(140.0, 320.0)) assertTrue(res12.shape contentEquals intArrayOf(2)) - val res32 = tensor3.bdot(tensor2) + val res32 = tensor3.matmul(tensor2) assertTrue(res32.mutableBuffer.array() contentEquals doubleArrayOf(-140.0)) assertTrue(res32.shape contentEquals intArrayOf(1, 1)) @@ -126,7 +126,7 @@ internal class TestDoubleTensorAlgebra { assertTrue(res11.mutableBuffer.array() contentEquals doubleArrayOf(22.0, 28.0, 49.0, 64.0)) assertTrue(res11.shape contentEquals intArrayOf(2, 2)) - val res45 = tensor4.bdot(tensor5) + val res45 = tensor4.matmul(tensor5) assertTrue(res45.mutableBuffer.array() contentEquals doubleArrayOf( 36.0, 42.0, 48.0, 81.0, 96.0, 111.0, 126.0, 150.0, 174.0, 468.0, 501.0, 534.0, 594.0, 636.0, 678.0, 720.0, 771.0, 822.0 -- 2.34.1 From a8182fad23417f4302ea77ccdeba3b931e50a471 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 4 Aug 2022 09:54:59 +0300 Subject: [PATCH 169/275] Multik went MPP --- CHANGELOG.md | 1 + benchmarks/build.gradle.kts | 10 ++++++--- .../kscience/kmath/benchmarks/DotBenchmark.kt | 3 +-- .../kmath/benchmarks/NDFieldBenchmark.kt | 6 ++---- .../kscience/kmath/benchmarks/globals.kt | 11 ++++++++++ build.gradle.kts | 2 ++ examples/build.gradle.kts | 3 +++ .../space/kscience/kmath/tensors/multik.kt | 9 +++++--- kmath-multik/build.gradle.kts | 21 +++++++++++++++---- .../kmath/multik/MultikDoubleAlgebra.kt | 9 +++++--- .../kmath/multik/MultikFloatAlgebra.kt | 9 +++++--- .../kscience/kmath/multik/MultikIntAlgebra.kt | 9 +++++--- .../kmath/multik/MultikLongAlgebra.kt | 9 +++++--- .../kmath/multik/MultikShortAlgebra.kt | 9 +++++--- .../kscience/kmath/multik/MultikTensor.kt | 1 + .../kmath/multik/MultikTensorAlgebra.kt | 18 +++++++++------- .../kscience/kmath/multik/MultikNDTest.kt | 16 +++++++------- 17 files changed, 100 insertions(+), 46 deletions(-) create mode 100644 benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/globals.kt rename kmath-multik/src/{main => commonMain}/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt (87%) rename kmath-multik/src/{main => commonMain}/kotlin/space/kscience/kmath/multik/MultikFloatAlgebra.kt (62%) rename kmath-multik/src/{main => commonMain}/kotlin/space/kscience/kmath/multik/MultikIntAlgebra.kt (63%) rename kmath-multik/src/{main => commonMain}/kotlin/space/kscience/kmath/multik/MultikLongAlgebra.kt (63%) rename kmath-multik/src/{main => commonMain}/kotlin/space/kscience/kmath/multik/MultikShortAlgebra.kt (62%) rename kmath-multik/src/{main => commonMain}/kotlin/space/kscience/kmath/multik/MultikTensor.kt (97%) rename kmath-multik/src/{main => commonMain}/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt (94%) rename kmath-multik/src/{test => commonTest}/kotlin/space/kscience/kmath/multik/MultikNDTest.kt (72%) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5ed80597..acec30836 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - Kotlin 1.7.20 - `LazyStructure` `deffered` -> `async` to comply with coroutines code style - Default `dot` operation in tensor algebra no longer support broadcasting. Instead `matmul` operation is added to `DoubleTensorAlgebra`. +- Multik went MPP ### Deprecated diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index e86990043..9c8dc613a 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -1,5 +1,6 @@ @file:Suppress("UNUSED_VARIABLE") +import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile import space.kscience.kmath.benchmarks.addBenchmarkProperties plugins { @@ -15,6 +16,8 @@ repositories { mavenCentral() } +val multikVersion: String by rootProject.extra + kotlin { jvm() @@ -39,7 +42,9 @@ kotlin { implementation(project(":kmath-dimensions")) implementation(project(":kmath-for-real")) implementation(project(":kmath-tensors")) - implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.4.2") + implementation(project(":kmath-multik")) + implementation("org.jetbrains.kotlinx:multik-default:$multikVersion") + implementation(npmlibs.kotlinx.benchmark.runtime) } } @@ -51,7 +56,6 @@ kotlin { implementation(project(":kmath-kotlingrad")) implementation(project(":kmath-viktor")) implementation(project(":kmath-jafama")) - implementation(project(":kmath-multik")) implementation(projects.kmath.kmathTensorflow) implementation("org.tensorflow:tensorflow-core-platform:0.4.0") implementation("org.nd4j:nd4j-native:1.0.0-M1") @@ -155,7 +159,7 @@ kotlin.sourceSets.all { } } -tasks.withType { +tasks.withType { kotlinOptions { jvmTarget = "11" freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" + "-Xlambdas=indy" diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt index 7ceecb5ab..d7ead6dd8 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt @@ -13,7 +13,6 @@ import space.kscience.kmath.commons.linear.CMLinearSpace import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM import space.kscience.kmath.linear.invoke import space.kscience.kmath.linear.linearSpace -import space.kscience.kmath.multik.multikAlgebra import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensorflow.produceWithTF @@ -78,7 +77,7 @@ internal class DotBenchmark { } @Benchmark - fun multikDot(blackhole: Blackhole) = with(DoubleField.multikAlgebra) { + fun multikDot(blackhole: Blackhole) = with(multikAlgebra) { blackhole.consume(matrix1 dot matrix2) } 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 89673acd4..eb5e1da47 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt @@ -13,7 +13,6 @@ import org.jetbrains.kotlinx.multik.api.Multik import org.jetbrains.kotlinx.multik.api.ones import org.jetbrains.kotlinx.multik.ndarray.data.DN import org.jetbrains.kotlinx.multik.ndarray.data.DataType -import space.kscience.kmath.multik.multikAlgebra import space.kscience.kmath.nd.BufferedFieldOpsND import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.ndAlgebra @@ -43,7 +42,7 @@ internal class NDFieldBenchmark { } @Benchmark - fun multikAdd(blackhole: Blackhole) = with(multikField) { + fun multikAdd(blackhole: Blackhole) = with(multikAlgebra) { var res: StructureND = one(shape) repeat(n) { res += 1.0 } blackhole.consume(res) @@ -71,7 +70,7 @@ internal class NDFieldBenchmark { } @Benchmark - fun multikInPlaceAdd(blackhole: Blackhole) = with(DoubleField.multikAlgebra) { + fun multikInPlaceAdd(blackhole: Blackhole) = with(multikAlgebra) { val res = Multik.ones(shape, DataType.DoubleDataType).wrap() repeat(n) { res += 1.0 } blackhole.consume(res) @@ -91,7 +90,6 @@ internal class NDFieldBenchmark { private val specializedField = DoubleField.ndAlgebra private val genericField = BufferedFieldOpsND(DoubleField) private val nd4jField = DoubleField.nd4j - private val multikField = DoubleField.multikAlgebra private val viktorField = DoubleField.viktorAlgebra } } diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/globals.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/globals.kt new file mode 100644 index 000000000..9f235c56e --- /dev/null +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/globals.kt @@ -0,0 +1,11 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.benchmarks + +import org.jetbrains.kotlinx.multik.default.DefaultEngine +import space.kscience.kmath.multik.MultikDoubleAlgebra + +val multikAlgebra = MultikDoubleAlgebra(DefaultEngine()) \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index c57b29105..b6e5b0748 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -74,3 +74,5 @@ ksciencePublish { } apiValidation.nonPublicMarkers.add("space.kscience.kmath.misc.UnstableKMathAPI") + +val multikVersion by extra("0.2.0") diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index cfa50815d..1d224bace 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -8,6 +8,8 @@ repositories { maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-js-wrappers") } +val multikVersion: String by rootProject.extra + dependencies { implementation(project(":kmath-ast")) implementation(project(":kmath-kotlingrad")) @@ -30,6 +32,7 @@ dependencies { implementation(project(":kmath-jafama")) //multik implementation(project(":kmath-multik")) + implementation("org.jetbrains.kotlinx:multik-default:$multikVersion") implementation("org.nd4j:nd4j-native:1.0.0-beta7") diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/multik.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/multik.kt index f2d1f0b41..7cf1c5120 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/multik.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/multik.kt @@ -7,11 +7,14 @@ package space.kscience.kmath.tensors import org.jetbrains.kotlinx.multik.api.Multik import org.jetbrains.kotlinx.multik.api.ndarray -import space.kscience.kmath.multik.multikAlgebra +import org.jetbrains.kotlinx.multik.default.DefaultEngine +import space.kscience.kmath.multik.MultikDoubleAlgebra import space.kscience.kmath.nd.one -import space.kscience.kmath.operations.DoubleField -fun main(): Unit = with(DoubleField.multikAlgebra) { + +val multikAlgebra = MultikDoubleAlgebra(DefaultEngine()) + +fun main(): Unit = with(multikAlgebra) { val a = Multik.ndarray(intArrayOf(1, 2, 3)).asType().wrap() val b = Multik.ndarray(doubleArrayOf(1.0, 2.0, 3.0)).wrap() one(a.shape) - a + b * 3.0 diff --git a/kmath-multik/build.gradle.kts b/kmath-multik/build.gradle.kts index ee31ead3c..39c03ab9b 100644 --- a/kmath-multik/build.gradle.kts +++ b/kmath-multik/build.gradle.kts @@ -1,12 +1,25 @@ plugins { - id("space.kscience.gradle.jvm") + id("space.kscience.gradle.mpp") } description = "JetBrains Multik connector" -dependencies { - api(project(":kmath-tensors")) - api("org.jetbrains.kotlinx:multik-default:0.2.0") +val multikVersion: String by rootProject.extra + +kotlin{ + sourceSets{ + commonMain{ + dependencies{ + api(project(":kmath-tensors")) + api("org.jetbrains.kotlinx:multik-core:$multikVersion") + } + } + commonTest{ + dependencies{ + api("org.jetbrains.kotlinx:multik-default:$multikVersion") + } + } + } } readme { diff --git a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt similarity index 87% rename from kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt rename to kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt index 1d4665618..dcc1623cc 100644 --- a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.multik +import org.jetbrains.kotlinx.multik.api.Engine import org.jetbrains.kotlinx.multik.api.Multik import org.jetbrains.kotlinx.multik.api.ndarrayOf import org.jetbrains.kotlinx.multik.ndarray.data.DataType @@ -14,7 +15,9 @@ import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.ExponentialOperations import space.kscience.kmath.operations.TrigonometricOperations -public object MultikDoubleAlgebra : MultikDivisionTensorAlgebra(), +public class MultikDoubleAlgebra( + multikEngine: Engine +) : MultikDivisionTensorAlgebra(multikEngine), TrigonometricOperations>, ExponentialOperations> { override val elementAlgebra: DoubleField get() = DoubleField override val type: DataType get() = DataType.DoubleDataType @@ -60,6 +63,6 @@ public object MultikDoubleAlgebra : MultikDivisionTensorAlgebra = Multik.ndarrayOf(value).wrap() } -public val Double.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikDoubleAlgebra -public val DoubleField.multikAlgebra: MultikTensorAlgebra get() = MultikDoubleAlgebra +//public val Double.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikDoubleAlgebra +//public val DoubleField.multikAlgebra: MultikTensorAlgebra get() = MultikDoubleAlgebra diff --git a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikFloatAlgebra.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikFloatAlgebra.kt similarity index 62% rename from kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikFloatAlgebra.kt rename to kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikFloatAlgebra.kt index 8dd9b3f60..db251b552 100644 --- a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikFloatAlgebra.kt +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikFloatAlgebra.kt @@ -5,12 +5,15 @@ package space.kscience.kmath.multik +import org.jetbrains.kotlinx.multik.api.Engine import org.jetbrains.kotlinx.multik.api.Multik import org.jetbrains.kotlinx.multik.api.ndarrayOf import org.jetbrains.kotlinx.multik.ndarray.data.DataType import space.kscience.kmath.operations.FloatField -public object MultikFloatAlgebra : MultikDivisionTensorAlgebra() { +public class MultikFloatAlgebra( + multikEngine: Engine +) : MultikDivisionTensorAlgebra(multikEngine) { override val elementAlgebra: FloatField get() = FloatField override val type: DataType get() = DataType.FloatDataType @@ -18,5 +21,5 @@ public object MultikFloatAlgebra : MultikDivisionTensorAlgebra get() = MultikFloatAlgebra -public val FloatField.multikAlgebra: MultikTensorAlgebra get() = MultikFloatAlgebra \ No newline at end of file +//public val Float.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikFloatAlgebra +//public val FloatField.multikAlgebra: MultikTensorAlgebra get() = MultikFloatAlgebra \ No newline at end of file diff --git a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikIntAlgebra.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikIntAlgebra.kt similarity index 63% rename from kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikIntAlgebra.kt rename to kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikIntAlgebra.kt index b9e0125e8..517845939 100644 --- a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikIntAlgebra.kt +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikIntAlgebra.kt @@ -5,16 +5,19 @@ package space.kscience.kmath.multik +import org.jetbrains.kotlinx.multik.api.Engine import org.jetbrains.kotlinx.multik.api.Multik import org.jetbrains.kotlinx.multik.api.ndarrayOf import org.jetbrains.kotlinx.multik.ndarray.data.DataType import space.kscience.kmath.operations.IntRing -public object MultikIntAlgebra : MultikTensorAlgebra() { +public class MultikIntAlgebra( + multikEngine: Engine +) : MultikTensorAlgebra(multikEngine) { override val elementAlgebra: IntRing get() = IntRing override val type: DataType get() = DataType.IntDataType override fun scalar(value: Int): MultikTensor = Multik.ndarrayOf(value).wrap() } -public val Int.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikIntAlgebra -public val IntRing.multikAlgebra: MultikTensorAlgebra get() = MultikIntAlgebra \ No newline at end of file +//public val Int.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikIntAlgebra +//public val IntRing.multikAlgebra: MultikTensorAlgebra get() = MultikIntAlgebra \ No newline at end of file diff --git a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikLongAlgebra.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikLongAlgebra.kt similarity index 63% rename from kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikLongAlgebra.kt rename to kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikLongAlgebra.kt index 1f3dfb0e5..9c6c1af54 100644 --- a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikLongAlgebra.kt +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikLongAlgebra.kt @@ -5,12 +5,15 @@ package space.kscience.kmath.multik +import org.jetbrains.kotlinx.multik.api.Engine import org.jetbrains.kotlinx.multik.api.Multik import org.jetbrains.kotlinx.multik.api.ndarrayOf import org.jetbrains.kotlinx.multik.ndarray.data.DataType import space.kscience.kmath.operations.LongRing -public object MultikLongAlgebra : MultikTensorAlgebra() { +public class MultikLongAlgebra( + multikEngine: Engine +) : MultikTensorAlgebra(multikEngine) { override val elementAlgebra: LongRing get() = LongRing override val type: DataType get() = DataType.LongDataType @@ -18,5 +21,5 @@ public object MultikLongAlgebra : MultikTensorAlgebra() { } -public val Long.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikLongAlgebra -public val LongRing.multikAlgebra: MultikTensorAlgebra get() = MultikLongAlgebra \ No newline at end of file +//public val Long.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikLongAlgebra +//public val LongRing.multikAlgebra: MultikTensorAlgebra get() = MultikLongAlgebra \ No newline at end of file diff --git a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikShortAlgebra.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikShortAlgebra.kt similarity index 62% rename from kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikShortAlgebra.kt rename to kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikShortAlgebra.kt index b9746571d..5288351b2 100644 --- a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikShortAlgebra.kt +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikShortAlgebra.kt @@ -5,16 +5,19 @@ package space.kscience.kmath.multik +import org.jetbrains.kotlinx.multik.api.Engine import org.jetbrains.kotlinx.multik.api.Multik import org.jetbrains.kotlinx.multik.api.ndarrayOf import org.jetbrains.kotlinx.multik.ndarray.data.DataType import space.kscience.kmath.operations.ShortRing -public object MultikShortAlgebra : MultikTensorAlgebra() { +public class MultikShortAlgebra( + multikEngine: Engine +) : MultikTensorAlgebra(multikEngine) { override val elementAlgebra: ShortRing get() = ShortRing override val type: DataType get() = DataType.ShortDataType override fun scalar(value: Short): MultikTensor = Multik.ndarrayOf(value).wrap() } -public val Short.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikShortAlgebra -public val ShortRing.multikAlgebra: MultikTensorAlgebra get() = MultikShortAlgebra \ No newline at end of file +//public val Short.Companion.multikAlgebra: MultikTensorAlgebra get() = MultikShortAlgebra +//public val ShortRing.multikAlgebra: MultikTensorAlgebra get() = MultikShortAlgebra \ No newline at end of file diff --git a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikTensor.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensor.kt similarity index 97% rename from kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikTensor.kt rename to kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensor.kt index 7efe672b4..3ab4b0e3d 100644 --- a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikTensor.kt +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensor.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlinx.multik.ndarray.data.* import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.Shape import space.kscience.kmath.tensors.api.Tensor +import kotlin.jvm.JvmInline @JvmInline public value class MultikTensor(public val array: MutableMultiArray) : Tensor { diff --git a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt similarity index 94% rename from kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt rename to kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt index 1cc1b9b6d..f9768ea39 100644 --- a/kmath-multik/src/main/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt @@ -20,14 +20,15 @@ import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.api.TensorAlgebra import space.kscience.kmath.tensors.api.TensorPartialDivisionAlgebra -public abstract class MultikTensorAlgebra> : TensorAlgebra - where T : Number, T : Comparable { +public abstract class MultikTensorAlgebra>( + private val multikEngine: Engine, +) : TensorAlgebra where T : Number, T : Comparable { public abstract val type: DataType - protected val multikMath: Math = mk.math - protected val multikLinAl: LinAlg = mk.linalg - protected val multikStat: Statistics = mk.stat + protected val multikMath: Math = multikEngine.getMath() + protected val multikLinAl: LinAlg = multikEngine.getLinAlg() + protected val multikStat: Statistics = multikEngine.getStatistics() override fun structureND(shape: Shape, initializer: A.(IntArray) -> T): MultikTensor { val strides = DefaultStrides(shape) @@ -255,12 +256,13 @@ public abstract class MultikTensorAlgebra> : TensorAlgebra override fun StructureND.argMax(dim: Int, keepDim: Boolean): Tensor { if (keepDim) TODO("keepDim not implemented") val res = multikMath.argMaxDN(asMultik().array, dim) - return with(MultikIntAlgebra) { res.wrap() } + return with(MultikIntAlgebra(multikEngine)) { res.wrap() } } } -public abstract class MultikDivisionTensorAlgebra> - : MultikTensorAlgebra(), TensorPartialDivisionAlgebra where T : Number, T : Comparable { +public abstract class MultikDivisionTensorAlgebra>( + multikEngine: Engine, +) : MultikTensorAlgebra(multikEngine), TensorPartialDivisionAlgebra where T : Number, T : Comparable { override fun T.div(arg: StructureND): MultikTensor = Multik.ones(arg.shape, type).apply { divAssign(arg.asMultik().array) }.wrap() diff --git a/kmath-multik/src/test/kotlin/space/kscience/kmath/multik/MultikNDTest.kt b/kmath-multik/src/commonTest/kotlin/space/kscience/kmath/multik/MultikNDTest.kt similarity index 72% rename from kmath-multik/src/test/kotlin/space/kscience/kmath/multik/MultikNDTest.kt rename to kmath-multik/src/commonTest/kotlin/space/kscience/kmath/multik/MultikNDTest.kt index 72c43d8e6..8bc43eef2 100644 --- a/kmath-multik/src/test/kotlin/space/kscience/kmath/multik/MultikNDTest.kt +++ b/kmath-multik/src/commonTest/kotlin/space/kscience/kmath/multik/MultikNDTest.kt @@ -5,33 +5,35 @@ package space.kscience.kmath.multik -import org.junit.jupiter.api.Test +import org.jetbrains.kotlinx.multik.default.DefaultEngine import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.one import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.DoubleTensorAlgebra import space.kscience.kmath.tensors.core.tensorAlgebra +import kotlin.test.Test import kotlin.test.assertTrue internal class MultikNDTest { + val multikAlgebra = MultikDoubleAlgebra(DefaultEngine()) + @Test - fun basicAlgebra(): Unit = DoubleField.multikAlgebra{ - one(2,2) + 1.0 + fun basicAlgebra(): Unit = with(multikAlgebra) { + one(2, 2) + 1.0 } @Test - fun dotResult(){ + fun dotResult() { val dim = 100 val tensor1 = DoubleTensorAlgebra.randomNormal(shape = intArrayOf(dim, dim), 12224) val tensor2 = DoubleTensorAlgebra.randomNormal(shape = intArrayOf(dim, dim), 12225) - val multikResult = with(DoubleField.multikAlgebra){ + val multikResult = with(multikAlgebra) { tensor1 dot tensor2 } - val defaultResult = with(DoubleField.tensorAlgebra){ + val defaultResult = with(DoubleField.tensorAlgebra) { tensor1 dot tensor2 } -- 2.34.1 From b6d2eb3b1b3ef37df5b02dfe5c4ef18b1e72ef6e Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Fri, 19 Aug 2022 15:19:01 +0300 Subject: [PATCH 170/275] Replace main `mipt-npm` appearances with `SciProgCentre`. Now link in "Documentation site (WIP)" works. --- README.md | 6 +++--- build.gradle.kts | 2 +- docs/templates/README-TEMPLATE.md | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index b9d36df50..03e803180 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [![JetBrains Research](https://jb.gg/badges/research.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) [![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382) -![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg) +![Gradle build](https://github.com/SciProgCentre/kmath/workflows/Gradle%20build/badge.svg) [![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22) [![Space](https://img.shields.io/badge/dynamic/xml?color=orange&label=Space&query=//metadata/versioning/latest&url=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fspace%2Fkscience%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/) @@ -11,7 +11,7 @@ analog to Python's NumPy library. Later we found that kotlin is much more flexib architecture designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like experience could be achieved with [kmath-for-real](/kmath-for-real) extension module. -[Documentation site (**WIP**)](https://mipt-npm.github.io/kmath/) +[Documentation site (**WIP**)](https://SciProgCentre.github.io/kmath/) ## Publications and talks @@ -325,4 +325,4 @@ Gradle `6.0+` is required for multiplatform artifacts. The project requires a lot of additional work. The most important thing we need is a feedback about what features are required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues marked with -[waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero) label. \ No newline at end of file +[waiting for a hero](https://github.com/SciProgCentre/kmath/labels/waiting%20for%20a%20hero) label. \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index b6e5b0748..d20d7f4ca 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -31,7 +31,7 @@ subprojects { localDirectory.set(kotlinDir) remoteUrl.set( - java.net.URL("https://github.com/mipt-npm/kmath/tree/master/${this@subprojects.name}/$kotlinDirPath") + java.net.URL("https://github.com/SciProgCentre/kmath/tree/master/${this@subprojects.name}/$kotlinDirPath") ) } diff --git a/docs/templates/README-TEMPLATE.md b/docs/templates/README-TEMPLATE.md index 1633f3ff1..d7d5a806d 100644 --- a/docs/templates/README-TEMPLATE.md +++ b/docs/templates/README-TEMPLATE.md @@ -1,6 +1,6 @@ [![JetBrains Research](https://jb.gg/badges/research.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) [![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382) -![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg) +![Gradle build](https://github.com/SciProgCentre/kmath/workflows/Gradle%20build/badge.svg) [![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22) [![Space](https://img.shields.io/badge/dynamic/xml?color=orange&label=Space&query=//metadata/versioning/latest&url=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fspace%2Fkscience%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/) @@ -11,7 +11,7 @@ analog to Python's NumPy library. Later we found that kotlin is much more flexib architecture designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like experience could be achieved with [kmath-for-real](/kmath-for-real) extension module. -[Documentation site (**WIP**)](https://mipt-npm.github.io/kmath/) +[Documentation site (**WIP**)](https://SciProgCentre.github.io/kmath/) ## Publications and talks -- 2.34.1 From efe14f50bf9c8aa8465d189b35acbdb5f5bba754 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Fri, 19 Aug 2022 15:59:13 +0300 Subject: [PATCH 171/275] #472: Update copyright. --- .idea/copyright/kmath.xml | 11 ++++++----- .idea/copyright/profiles_settings.xml | 2 +- .../benchmarks/ExpressionsInterpretersBenchmark.kt | 2 +- .../space/kscience/kmath/benchmarks/ArrayBenchmark.kt | 2 +- .../kscience/kmath/benchmarks/BigIntBenchmark.kt | 2 +- .../kscience/kmath/benchmarks/BufferBenchmark.kt | 2 +- .../space/kscience/kmath/benchmarks/DotBenchmark.kt | 2 +- .../benchmarks/ExpressionsInterpretersBenchmark.kt | 2 +- .../kscience/kmath/benchmarks/JafamaBenchmark.kt | 2 +- .../kmath/benchmarks/MatrixInverseBenchmark.kt | 2 +- .../kscience/kmath/benchmarks/NDFieldBenchmark.kt | 2 +- .../kmath/benchmarks/TensorAlgebraBenchmark.kt | 2 +- .../kscience/kmath/benchmarks/ViktorBenchmark.kt | 2 +- .../kscience/kmath/benchmarks/ViktorLogBenchmark.kt | 2 +- .../kotlin/space/kscience/kmath/benchmarks/globals.kt | 2 +- .../space/kscience/kmath/benchmarks/JmhReport.kt | 2 +- .../kmath/benchmarks/addBenchmarkProperties.kt | 2 +- .../space/kscience/kmath/ejml/codegen/ejmlCodegen.kt | 2 +- docs/images/KM.svg | 2 +- docs/images/KM_mono.svg | 2 +- docs/images/KMath.svg | 2 +- docs/images/KMath_mono.svg | 2 +- .../kotlin/space/kscience/kmath/ast/astRendering.kt | 2 +- .../kotlin/space/kscience/kmath/ast/expressions.kt | 2 +- .../space/kscience/kmath/ast/kotlingradSupport.kt | 2 +- .../kotlin/space/kscience/kmath/ast/symjaSupport.kt | 2 +- .../kotlin/space/kscience/kmath/fit/chiSquared.kt | 2 +- .../main/kotlin/space/kscience/kmath/fit/qowFit.kt | 2 +- .../space/kscience/kmath/functions/integrate.kt | 2 +- .../space/kscience/kmath/functions/interpolate.kt | 2 +- .../kscience/kmath/functions/interpolateSquare.kt | 2 +- .../kscience/kmath/functions/matrixIntegration.kt | 2 +- .../space/kscience/kmath/functions/polynomials.kt | 2 +- .../kotlin/space/kscience/kmath/jafama/JafamaDemo.kt | 2 +- .../space/kscience/kmath/linear/dotPerformance.kt | 2 +- .../kotlin/space/kscience/kmath/linear/gradient.kt | 2 +- .../space/kscience/kmath/operations/BigIntDemo.kt | 2 +- .../space/kscience/kmath/operations/complexDemo.kt | 2 +- .../kscience/kmath/operations/mixedNDOperations.kt | 2 +- .../kscience/kmath/stat/DistributionBenchmark.kt | 2 +- .../space/kscience/kmath/stat/DistributionDemo.kt | 2 +- .../space/kscience/kmath/structures/ComplexND.kt | 2 +- .../kotlin/space/kscience/kmath/structures/NDField.kt | 2 +- .../kscience/kmath/structures/StreamDoubleFieldND.kt | 2 +- .../kmath/structures/StructureReadBenchmark.kt | 2 +- .../kmath/structures/StructureWriteBenchmark.kt | 2 +- .../kotlin/space/kscience/kmath/structures/buffers.kt | 2 +- .../kscience/kmath/structures/typeSafeDimensions.kt | 2 +- .../kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt | 2 +- .../main/kotlin/space/kscience/kmath/tensors/PCA.kt | 2 +- .../kscience/kmath/tensors/dataSetNormalization.kt | 2 +- .../kmath/tensors/linearSystemSolvingWithLUP.kt | 2 +- .../kotlin/space/kscience/kmath/tensors/multik.kt | 2 +- .../space/kscience/kmath/tensors/neuralNetwork.kt | 2 +- .../kotlin/space/kscience/kmath/ast/TypedMst.kt | 2 +- .../space/kscience/kmath/ast/evaluateConstants.kt | 2 +- .../kotlin/space/kscience/kmath/ast/parser.kt | 2 +- .../kmath/ast/rendering/LatexSyntaxRenderer.kt | 2 +- .../kmath/ast/rendering/MathMLSyntaxRenderer.kt | 2 +- .../kscience/kmath/ast/rendering/MathRenderer.kt | 2 +- .../space/kscience/kmath/ast/rendering/MathSyntax.kt | 2 +- .../kscience/kmath/ast/rendering/SyntaxRenderer.kt | 2 +- .../space/kscience/kmath/ast/rendering/features.kt | 2 +- .../kmath/ast/rendering/multiplatformToString.kt | 2 +- .../space/kscience/kmath/ast/rendering/phases.kt | 2 +- .../ast/TestCompilerConsistencyWithInterpreter.kt | 2 +- .../kscience/kmath/ast/TestCompilerOperations.kt | 2 +- .../space/kscience/kmath/ast/TestCompilerVariables.kt | 2 +- .../kotlin/space/kscience/kmath/ast/TestFolding.kt | 2 +- .../kotlin/space/kscience/kmath/ast/TestParser.kt | 2 +- .../space/kscience/kmath/ast/TestParserPrecedence.kt | 2 +- .../kscience/kmath/ast/rendering/TestFeatures.kt | 2 +- .../space/kscience/kmath/ast/rendering/TestLatex.kt | 2 +- .../space/kscience/kmath/ast/rendering/TestMathML.kt | 2 +- .../space/kscience/kmath/ast/rendering/TestStages.kt | 2 +- .../space/kscience/kmath/ast/rendering/TestUtils.kt | 2 +- .../kotlin/space/kscience/kmath/ast/utils.kt | 2 +- .../kmath/ast/rendering/multiplatformToString.kt | 2 +- .../kotlin/space/kscience/kmath/estree/estree.kt | 2 +- .../kscience/kmath/estree/internal/ESTreeBuilder.kt | 2 +- .../estree/internal/astring/astring.typealises.kt | 2 +- .../space/kscience/kmath/internal/astring/astring.kt | 2 +- .../kmath/internal/astring/astring.typealises.kt | 2 +- .../space/kscience/kmath/internal/base64/base64.kt | 2 +- .../kmath/internal/binaryen/index.binaryen.kt | 2 +- .../internal/binaryen/index.binaryen.typealiases.kt | 2 +- .../space/kscience/kmath/internal/emitter/emitter.kt | 2 +- .../kmath/internal/estree/estree.extensions.kt | 2 +- .../space/kscience/kmath/internal/estree/estree.kt | 2 +- .../space/kscience/kmath/internal/stream/stream.kt | 2 +- .../kmath/internal/tsstdlib/lib.es2015.iterable.kt | 2 +- .../space/kscience/kmath/internal/tsstdlib/lib.es5.kt | 2 +- .../webassembly/lib.dom.WebAssembly.module_dukat.kt | 2 +- .../webassembly/nonDeclarations.WebAssembly.kt | 2 +- .../space/kscience/kmath/wasm/internal/WasmBuilder.kt | 2 +- .../kmath/wasm/internal/f64StandardFunctions.kt | 2 +- .../jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt | 2 +- .../jsTest/kotlin/space/kscience/kmath/ast/utils.kt | 2 +- .../space/kscience/kmath/wasm/TestWasmSpecific.kt | 2 +- .../jvmMain/kotlin/space/kscience/kmath/asm/asm.kt | 2 +- .../space/kscience/kmath/asm/internal/AsmBuilder.kt | 2 +- .../kscience/kmath/asm/internal/GenericAsmBuilder.kt | 2 +- .../kmath/asm/internal/PrimitiveAsmBuilder.kt | 2 +- .../space/kscience/kmath/asm/internal/codegenUtils.kt | 2 +- .../kscience/kmath/asm/internal/mapIntrinsics.kt | 2 +- .../kmath/ast/rendering/multiplatformToString.kt | 2 +- .../jvmTest/kotlin/space/kscience/kmath/ast/utils.kt | 2 +- .../expressions/DerivativeStructureExpression.kt | 2 +- .../commons/integration/CMGaussRuleIntegrator.kt | 2 +- .../kmath/commons/integration/CMIntegrator.kt | 2 +- .../space/kscience/kmath/commons/linear/CMMatrix.kt | 2 +- .../space/kscience/kmath/commons/linear/CMSolver.kt | 2 +- .../kmath/commons/optimization/CMOptimizer.kt | 2 +- .../kmath/commons/random/CMRandomGeneratorWrapper.kt | 2 +- .../kmath/commons/transform/Transformations.kt | 2 +- .../expressions/DerivativeStructureExpressionTest.kt | 2 +- .../kmath/commons/integration/IntegrationTest.kt | 2 +- .../kmath/commons/optimization/OptimizeTest.kt | 2 +- .../kotlin/space/kscience/kmath/complex/Complex.kt | 2 +- .../space/kscience/kmath/complex/ComplexFieldND.kt | 2 +- .../kotlin/space/kscience/kmath/complex/Quaternion.kt | 2 +- .../kscience/kmath/complex/ComplexBufferSpecTest.kt | 2 +- .../space/kscience/kmath/complex/ComplexFieldTest.kt | 2 +- .../space/kscience/kmath/complex/ComplexTest.kt | 2 +- .../kmath/complex/ExpressionFieldForComplexTest.kt | 2 +- .../space/kscience/kmath/complex/QuaternionTest.kt | 2 +- .../kotlin/space/kscience/kmath/data/ColumnarData.kt | 2 +- .../space/kscience/kmath/data/XYColumnarData.kt | 2 +- .../space/kscience/kmath/data/XYErrorColumnarData.kt | 2 +- .../space/kscience/kmath/data/XYZColumnarData.kt | 2 +- .../kotlin/space/kscience/kmath/domains/Domain.kt | 2 +- .../kotlin/space/kscience/kmath/domains/Domain1D.kt | 2 +- .../space/kscience/kmath/domains/DoubleDomain.kt | 2 +- .../space/kscience/kmath/domains/HyperSquareDomain.kt | 2 +- .../kscience/kmath/domains/UnconstrainedDomain.kt | 2 +- .../space/kscience/kmath/expressions/DSAlgebra.kt | 4 ++-- .../space/kscience/kmath/expressions/DSCompiler.kt | 4 ++-- .../kmath/expressions/DifferentiableExpression.kt | 2 +- .../space/kscience/kmath/expressions/Expression.kt | 2 +- .../kmath/expressions/FunctionalExpressionAlgebra.kt | 2 +- .../kotlin/space/kscience/kmath/expressions/MST.kt | 2 +- .../space/kscience/kmath/expressions/MstAlgebra.kt | 2 +- .../kscience/kmath/expressions/SimpleAutoDiff.kt | 2 +- .../kotlin/space/kscience/kmath/expressions/Symbol.kt | 2 +- .../space/kscience/kmath/expressions/SymbolIndexer.kt | 2 +- .../kscience/kmath/expressions/specialExpressions.kt | 2 +- .../kscience/kmath/linear/BufferedLinearSpace.kt | 2 +- .../space/kscience/kmath/linear/DoubleLinearSpace.kt | 2 +- .../space/kscience/kmath/linear/LinearSolver.kt | 2 +- .../kotlin/space/kscience/kmath/linear/LinearSpace.kt | 2 +- .../space/kscience/kmath/linear/LupDecomposition.kt | 2 +- .../space/kscience/kmath/linear/MatrixBuilder.kt | 2 +- .../space/kscience/kmath/linear/MatrixFeatures.kt | 2 +- .../space/kscience/kmath/linear/MatrixWrapper.kt | 2 +- .../space/kscience/kmath/linear/VirtualMatrix.kt | 2 +- .../kotlin/space/kscience/kmath/misc/Featured.kt | 2 +- .../kotlin/space/kscience/kmath/misc/annotations.kt | 2 +- .../kotlin/space/kscience/kmath/misc/cumulative.kt | 2 +- .../kotlin/space/kscience/kmath/misc/logging.kt | 2 +- .../kotlin/space/kscience/kmath/misc/numbers.kt | 2 +- .../kotlin/space/kscience/kmath/misc/sorting.kt | 4 ++-- .../kotlin/space/kscience/kmath/nd/AlgebraND.kt | 2 +- .../kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt | 2 +- .../kotlin/space/kscience/kmath/nd/BufferND.kt | 2 +- .../kotlin/space/kscience/kmath/nd/DoubleFieldND.kt | 2 +- .../kotlin/space/kscience/kmath/nd/Shape.kt | 2 +- .../kotlin/space/kscience/kmath/nd/ShapeIndexer.kt | 2 +- .../kotlin/space/kscience/kmath/nd/ShortRingND.kt | 2 +- .../kotlin/space/kscience/kmath/nd/Structure1D.kt | 2 +- .../kotlin/space/kscience/kmath/nd/Structure2D.kt | 2 +- .../kotlin/space/kscience/kmath/nd/StructureND.kt | 2 +- .../space/kscience/kmath/nd/VirtualStructureND.kt | 2 +- .../space/kscience/kmath/nd/algebraNDExtentions.kt | 2 +- .../kotlin/space/kscience/kmath/nd/operationsND.kt | 2 +- .../kotlin/space/kscience/kmath/operations/Algebra.kt | 2 +- .../kotlin/space/kscience/kmath/operations/BigInt.kt | 2 +- .../space/kscience/kmath/operations/BufferAlgebra.kt | 2 +- .../kscience/kmath/operations/DoubleBufferField.kt | 2 +- .../kscience/kmath/operations/DoubleBufferOps.kt | 2 +- .../space/kscience/kmath/operations/LogicAlgebra.kt | 2 +- .../space/kscience/kmath/operations/NumericAlgebra.kt | 2 +- .../kscience/kmath/operations/OptionalOperations.kt | 2 +- .../kscience/kmath/operations/algebraExtensions.kt | 2 +- .../kscience/kmath/operations/bufferOperation.kt | 2 +- .../kotlin/space/kscience/kmath/operations/numbers.kt | 2 +- .../space/kscience/kmath/structures/ArrayBuffer.kt | 2 +- .../kotlin/space/kscience/kmath/structures/Buffer.kt | 2 +- .../kscience/kmath/structures/BufferAccessor2D.kt | 2 +- .../space/kscience/kmath/structures/ByteBuffer.kt | 2 +- .../space/kscience/kmath/structures/DoubleBuffer.kt | 2 +- .../space/kscience/kmath/structures/FlaggedBuffer.kt | 2 +- .../space/kscience/kmath/structures/FloatBuffer.kt | 2 +- .../space/kscience/kmath/structures/IntBuffer.kt | 2 +- .../space/kscience/kmath/structures/ListBuffer.kt | 2 +- .../space/kscience/kmath/structures/LongBuffer.kt | 2 +- .../space/kscience/kmath/structures/MemoryBuffer.kt | 2 +- .../space/kscience/kmath/structures/MutableBuffer.kt | 2 +- .../space/kscience/kmath/structures/ShortBuffer.kt | 2 +- .../kotlin/space/kscience/kmath/expressions/DSTest.kt | 4 ++-- .../kscience/kmath/expressions/ExpressionFieldTest.kt | 2 +- .../space/kscience/kmath/expressions/InterpretTest.kt | 2 +- .../kscience/kmath/expressions/SimpleAutoDiffTest.kt | 2 +- .../space/kscience/kmath/linear/DoubleLUSolverTest.kt | 2 +- .../kotlin/space/kscience/kmath/linear/MatrixTest.kt | 2 +- .../space/kscience/kmath/misc/CumulativeKtTest.kt | 2 +- .../kotlin/space/kscience/kmath/misc/PermSortTest.kt | 4 ++-- .../space/kscience/kmath/nd/NdOperationsTest.kt | 2 +- .../kscience/kmath/operations/BigIntAlgebraTest.kt | 2 +- .../kmath/operations/BigIntConstructorTest.kt | 2 +- .../kmath/operations/BigIntConversionsTest.kt | 2 +- .../kscience/kmath/operations/BigIntOperationsTest.kt | 2 +- .../kscience/kmath/operations/DoubleFieldTest.kt | 2 +- .../space/kscience/kmath/structures/NDFieldTest.kt | 2 +- .../kscience/kmath/structures/NumberNDFieldTest.kt | 2 +- .../kotlin/space/kscience/kmath/misc/numbers.kt | 2 +- .../space/kscience/kmath/operations/isInteger.kt | 2 +- .../kotlin/space/kscience/kmath/misc/numbersJVM.kt | 2 +- .../space/kscience/kmath/operations/BigNumbers.kt | 2 +- .../space/kscience/kmath/operations/isInteger.kt | 2 +- .../kotlin/space/kscience/kmath/misc/numbers.kt | 2 +- .../space/kscience/kmath/operations/isInteger.kt | 2 +- .../space/kscience/kmath/chains/BlockingChain.kt | 2 +- .../kscience/kmath/chains/BlockingDoubleChain.kt | 2 +- .../space/kscience/kmath/chains/BlockingIntChain.kt | 2 +- .../kotlin/space/kscience/kmath/chains/Chain.kt | 2 +- .../kotlin/space/kscience/kmath/chains/flowExtra.kt | 2 +- .../kscience/kmath/coroutines/coroutinesExtra.kt | 2 +- .../space/kscience/kmath/streaming/BufferFlow.kt | 2 +- .../space/kscience/kmath/streaming/RingBuffer.kt | 2 +- .../kotlin/space/kscience/kmath/chains/ChainExt.kt | 2 +- .../kscience/kmath/structures/LazyStructureND.kt | 2 +- .../space/kscience/kmath/streaming/BufferFlowTest.kt | 2 +- .../space/kscience/kmath/streaming/RingBufferTest.kt | 2 +- .../space/kscience/kmath/dimensions/Dimension.kt | 2 +- .../space/kscience/kmath/dimensions/Wrappers.kt | 2 +- .../space/kscience/dimensions/DMatrixContextTest.kt | 2 +- .../space/kscience/kmath/dimensions/Dimension.kt | 2 +- .../space/kscience/kmath/dimensions/Dimension.kt | 2 +- .../space/kscience/kmath/dimensions/Dimension.kt | 2 +- .../space/kscience/kmath/ejml/EjmlLinearSpace.kt | 2 +- .../kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt | 2 +- .../kotlin/space/kscience/kmath/ejml/EjmlVector.kt | 2 +- .../kotlin/space/kscience/kmath/ejml/_generated.kt | 4 ++-- .../space/kscience/kmath/ejml/EjmlMatrixTest.kt | 2 +- .../space/kscience/kmath/ejml/EjmlVectorTest.kt | 2 +- .../kotlin/space/kscience/kmath/real/DoubleVector.kt | 2 +- .../kotlin/space/kscience/kmath/real/RealMatrix.kt | 2 +- .../kotlin/space/kscience/kmath/real/dot.kt | 2 +- .../kotlin/space/kscience/kmath/real/grids.kt | 2 +- .../kotlin/space/kscience/kmath/real/realND.kt | 2 +- .../space/kscience/kmath/real/DoubleMatrixTest.kt | 2 +- .../space/kscience/kmath/real/DoubleVectorTest.kt | 2 +- .../kotlin/space/kscience/kmath/real/GridTest.kt | 2 +- .../space/kscience/kmath/functions/Piecewise.kt | 2 +- .../space/kscience/kmath/functions/Polynomial.kt | 2 +- .../space/kscience/kmath/functions/functionTypes.kt | 2 +- .../kmath/functions/polynomialConstructors.kt | 2 +- .../space/kscience/kmath/functions/polynomialUtil.kt | 2 +- .../kscience/kmath/integration/GaussIntegrator.kt | 2 +- .../kmath/integration/GaussIntegratorRuleFactory.kt | 2 +- .../space/kscience/kmath/integration/Integrand.kt | 2 +- .../space/kscience/kmath/integration/Integrator.kt | 2 +- .../kmath/integration/MultivariateIntegrand.kt | 2 +- .../kscience/kmath/integration/SimpsonIntegrator.kt | 2 +- .../kscience/kmath/integration/SplineIntegrator.kt | 2 +- .../kscience/kmath/integration/UnivariateIntegrand.kt | 2 +- .../kscience/kmath/interpolation/Interpolator.kt | 2 +- .../kmath/interpolation/LinearInterpolator.kt | 2 +- .../kmath/interpolation/SplineInterpolator.kt | 2 +- .../space/kscience/kmath/functions/PolynomialTest.kt | 2 +- .../kscience/kmath/functions/PolynomialUtilTest.kt | 2 +- .../kscience/kmath/functions/testUtils/IntModulo.kt | 2 +- .../kmath/functions/testUtils/IntModuloUtils.kt | 2 +- .../kscience/kmath/functions/testUtils/Rational.kt | 2 +- .../space/kscience/kmath/functions/testUtils/misc.kt | 2 +- .../kscience/kmath/integration/GaussIntegralTest.kt | 2 +- .../kscience/kmath/integration/SimpsonIntegralTest.kt | 2 +- .../kscience/kmath/integration/SplineIntegralTest.kt | 2 +- .../kmath/interpolation/LinearInterpolatorTest.kt | 2 +- .../kmath/interpolation/SplineInterpolatorTest.kt | 2 +- .../kotlin/space/kscience/kmath/geometry/Circle2D.kt | 2 +- .../space/kscience/kmath/geometry/Euclidean2DSpace.kt | 2 +- .../space/kscience/kmath/geometry/Euclidean3DSpace.kt | 2 +- .../space/kscience/kmath/geometry/GeometrySpace.kt | 2 +- .../kotlin/space/kscience/kmath/geometry/Line.kt | 2 +- .../space/kscience/kmath/geometry/ReferenceFrame.kt | 2 +- .../space/kscience/kmath/geometry/projections.kt | 2 +- .../space/kscience/kmath/geometry/rotations3D.kt | 2 +- .../kscience/kmath/geometry/Euclidean2DSpaceTest.kt | 2 +- .../kscience/kmath/geometry/Euclidean3DSpaceTest.kt | 2 +- .../kscience/kmath/geometry/ProjectionAlongTest.kt | 2 +- .../kscience/kmath/geometry/ProjectionOntoLineTest.kt | 2 +- .../space/kscience/kmath/geometry/RotationTest.kt | 2 +- .../space/kscience/kmath/geometry/Vector2DTest.kt | 2 +- .../space/kscience/kmath/geometry/Vector3DTest.kt | 2 +- .../kotlin/space/kscience/kmath/geometry/testUtils.kt | 2 +- .../kotlin/space/kscience/kmath/histogram/Counter.kt | 2 +- .../space/kscience/kmath/histogram/Histogram.kt | 2 +- .../space/kscience/kmath/histogram/Histogram1D.kt | 2 +- .../space/kscience/kmath/histogram/HistogramND.kt | 2 +- .../kscience/kmath/histogram/UniformHistogram1D.kt | 2 +- .../kmath/histogram/UniformHistogramGroupND.kt | 2 +- .../kmath/histogram/MultivariateHistogramTest.kt | 2 +- .../kmath/histogram/UniformHistogram1DTest.kt | 2 +- .../kscience/kmath/histogram/TreeHistogramGroup.kt | 2 +- .../kscience/kmath/histogram/TreeHistogramTest.kt | 2 +- .../kotlin/space/kscience/kmath/jafama/KMathJafama.kt | 2 +- .../space/kscience/kmath/jupyter/KMathJupyter.kt | 2 +- .../space/kscience/kmath/kotlingrad/KMathNumber.kt | 2 +- .../kscience/kmath/kotlingrad/KotlingradExpression.kt | 2 +- .../kscience/kmath/kotlingrad/scalarsAdapters.kt | 2 +- .../space/kscience/kmath/kotlingrad/AdaptingTests.kt | 2 +- .../kotlin/space/kscience/kmath/memory/Memory.kt | 2 +- .../kotlin/space/kscience/kmath/memory/MemorySpec.kt | 2 +- .../space/kscience/kmath/memory/DataViewMemory.kt | 2 +- .../space/kscience/kmath/memory/ByteBufferMemory.kt | 2 +- .../space/kscience/kmath/memory/NativeMemory.kt | 2 +- .../kscience/kmath/multik/MultikDoubleAlgebra.kt | 2 +- .../space/kscience/kmath/multik/MultikFloatAlgebra.kt | 2 +- .../space/kscience/kmath/multik/MultikIntAlgebra.kt | 2 +- .../space/kscience/kmath/multik/MultikLongAlgebra.kt | 2 +- .../space/kscience/kmath/multik/MultikShortAlgebra.kt | 2 +- .../space/kscience/kmath/multik/MultikTensor.kt | 2 +- .../kscience/kmath/multik/MultikTensorAlgebra.kt | 2 +- .../space/kscience/kmath/multik/MultikNDTest.kt | 2 +- .../space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt | 2 +- .../space/kscience/kmath/nd4j/Nd4jArrayIterator.kt | 2 +- .../space/kscience/kmath/nd4j/Nd4jArrayStructure.kt | 2 +- .../space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt | 2 +- .../main/kotlin/space/kscience/kmath/nd4j/arrays.kt | 2 +- .../space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt | 2 +- .../kscience/kmath/nd4j/Nd4jArrayStructureTest.kt | 2 +- .../kmath/optimization/FunctionOptimization.kt | 2 +- .../kmath/optimization/OptimizationBuilder.kt | 2 +- .../kmath/optimization/OptimizationProblem.kt | 2 +- .../space/kscience/kmath/optimization/Optimizer.kt | 2 +- .../space/kscience/kmath/optimization/QowOptimizer.kt | 2 +- .../kotlin/space/kscience/kmath/optimization/XYFit.kt | 2 +- .../kscience/kmath/optimization/logLikelihood.kt | 2 +- .../kscience/kmath/functions/LabeledPolynomial.kt | 2 +- .../kmath/functions/LabeledRationalFunction.kt | 2 +- .../space/kscience/kmath/functions/ListPolynomial.kt | 2 +- .../kscience/kmath/functions/ListRationalFunction.kt | 2 +- .../kscience/kmath/functions/NumberedPolynomial.kt | 2 +- .../kmath/functions/NumberedRationalFunction.kt | 2 +- .../space/kscience/kmath/functions/Polynomial.kt | 2 +- .../kscience/kmath/functions/RationalFunction.kt | 2 +- .../space/kscience/kmath/functions/algebraicStub.kt | 2 +- .../space/kscience/kmath/functions/collectionUtils.kt | 2 +- .../kscience/kmath/functions/labeledConstructors.kt | 2 +- .../space/kscience/kmath/functions/labeledUtil.kt | 2 +- .../kscience/kmath/functions/listConstructors.kt | 2 +- .../kotlin/space/kscience/kmath/functions/listUtil.kt | 2 +- .../kotlin/space/kscience/kmath/functions/misc.kt | 2 +- .../kscience/kmath/functions/numberedConstructors.kt | 2 +- .../space/kscience/kmath/functions/numberedUtil.kt | 2 +- .../kscience/kmath/functions/AlgebraicStubTest.kt | 2 +- .../kmath/functions/LabeledConstructorsTest.kt | 2 +- .../kscience/kmath/functions/LabeledPolynomialTest.kt | 2 +- .../kmath/functions/LabeledPolynomialUtilTest.kt | 2 +- .../kscience/kmath/functions/ListPolynomialTest.kt | 2 +- .../kmath/functions/ListPolynomialUtilTest.kt | 2 +- .../kmath/functions/NumberedConstructorsTest.kt | 2 +- .../kmath/functions/NumberedPolynomialTest.kt | 2 +- .../kmath/functions/NumberedPolynomialUtilTest.kt | 2 +- .../kscience/kmath/functions/testUtils/BufferUtils.kt | 2 +- .../kscience/kmath/functions/testUtils/IntModulo.kt | 2 +- .../kmath/functions/testUtils/IntModuloUtils.kt | 2 +- .../kscience/kmath/functions/testUtils/NTMisc.kt | 2 +- .../kscience/kmath/functions/testUtils/Rational.kt | 2 +- .../kscience/kmath/functions/testUtils/assertion.kt | 2 +- .../space/kscience/kmath/functions/testUtils/misc.kt | 2 +- .../kscience/kmath/distributions/Distribution.kt | 2 +- .../kmath/distributions/FactorizedDistribution.kt | 2 +- .../kmath/distributions/NormalDistribution.kt | 2 +- .../space/kscience/kmath/internal/InternalErf.kt | 2 +- .../space/kscience/kmath/internal/InternalGamma.kt | 2 +- .../space/kscience/kmath/internal/InternalUtils.kt | 2 +- .../kmath/samplers/AhrensDieterExponentialSampler.kt | 2 +- .../AhrensDieterMarsagliaTsangGammaSampler.kt | 2 +- .../kmath/samplers/AliasMethodDiscreteSampler.kt | 2 +- .../space/kscience/kmath/samplers/BoxMullerSampler.kt | 2 +- .../space/kscience/kmath/samplers/GaussianSampler.kt | 2 +- .../kmath/samplers/KempSmallMeanPoissonSampler.kt | 2 +- .../samplers/MarsagliaNormalizedGaussianSampler.kt | 2 +- .../kmath/samplers/NormalizedGaussianSampler.kt | 2 +- .../space/kscience/kmath/samplers/PoissonSampler.kt | 2 +- .../samplers/ZigguratNormalizedGaussianSampler.kt | 2 +- .../kotlin/space/kscience/kmath/stat/MCScope.kt | 2 +- .../kotlin/space/kscience/kmath/stat/Mean.kt | 2 +- .../kotlin/space/kscience/kmath/stat/Median.kt | 2 +- .../kotlin/space/kscience/kmath/stat/RandomChain.kt | 2 +- .../space/kscience/kmath/stat/RandomGenerator.kt | 2 +- .../kotlin/space/kscience/kmath/stat/Sampler.kt | 2 +- .../space/kscience/kmath/stat/SamplerAlgebra.kt | 2 +- .../kotlin/space/kscience/kmath/stat/Statistic.kt | 2 +- .../space/kscience/kmath/stat/UniformDistribution.kt | 2 +- .../space/kscience/kmath/stat/ValueAndErrorField.kt | 2 +- .../kscience/kmath/stat/RandomSourceGenerator.kt | 2 +- .../kscience/kmath/stat/CommonsDistributionsTest.kt | 2 +- .../kotlin/space/kscience/kmath/stat/MCScopeTest.kt | 2 +- .../kotlin/space/kscience/kmath/stat/SamplerTest.kt | 2 +- .../kotlin/space/kscience/kmath/stat/StatisticTest.kt | 2 +- .../space/kscience/kmath/symja/SymjaExpression.kt | 2 +- .../kotlin/space/kscience/kmath/symja/adapters.kt | 2 +- .../kmath/tensorflow/DoubleTensorFlowAlgebra.kt | 5 +++++ .../kscience/kmath/tensorflow/IntTensorFlowAlgebra.kt | 5 +++++ .../kscience/kmath/tensorflow/TensorFlowAlgebra.kt | 5 +++++ .../space/kscience/kmath/tensorflow/tfOperations.kt | 2 +- .../kscience/kmath/tensorflow/DoubleTensorFlowOps.kt | 5 +++++ .../kmath/tensors/api/AnalyticTensorAlgebra.kt | 2 +- .../kmath/tensors/api/LinearOpsTensorAlgebra.kt | 2 +- .../kotlin/space/kscience/kmath/tensors/api/Tensor.kt | 2 +- .../space/kscience/kmath/tensors/api/TensorAlgebra.kt | 2 +- .../kmath/tensors/api/TensorPartialDivisionAlgebra.kt | 2 +- .../tensors/core/BroadcastDoubleTensorAlgebra.kt | 2 +- .../kscience/kmath/tensors/core/BufferedTensor.kt | 2 +- .../space/kscience/kmath/tensors/core/DoubleTensor.kt | 2 +- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 2 +- .../space/kscience/kmath/tensors/core/IntTensor.kt | 2 +- .../kmath/tensors/core/TensorLinearStructure.kt | 2 +- .../kmath/tensors/core/internal/broadcastUtils.kt | 2 +- .../kscience/kmath/tensors/core/internal/checks.kt | 2 +- .../kscience/kmath/tensors/core/internal/linUtils.kt | 2 +- .../kmath/tensors/core/internal/tensorCastsUtils.kt | 2 +- .../kscience/kmath/tensors/core/internal/utils.kt | 2 +- .../kmath/tensors/core/tensorAlgebraExtensions.kt | 2 +- .../space/kscience/kmath/tensors/core/tensorCasts.kt | 2 +- .../kscience/kmath/tensors/core/TestBroadcasting.kt | 2 +- .../tensors/core/TestDoubleAnalyticTensorAlgebra.kt | 2 +- .../kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt | 2 +- .../kscience/kmath/tensors/core/TestDoubleTensor.kt | 2 +- .../kmath/tensors/core/TestDoubleTensorAlgebra.kt | 2 +- .../space/kscience/kmath/trajectory/DubinsPath.kt | 2 +- .../kotlin/space/kscience/kmath/trajectory/Pose2D.kt | 2 +- .../space/kscience/kmath/trajectory/Trajectory.kt | 2 +- .../space/kscience/kmath/trajectory/TrajectoryCost.kt | 2 +- .../kotlin/space/kscience/kmath/trajectory/route.kt | 2 +- .../kotlin/space/kscience/kmath/trajectory/Math.kt | 5 +++++ .../kscience/kmath/trajectory/dubins/DubinsTests.kt | 2 +- .../kscience/kmath/trajectory/segments/ArcTests.kt | 5 +++++ .../kscience/kmath/trajectory/segments/CircleTests.kt | 2 +- .../kscience/kmath/trajectory/segments/LineTests.kt | 5 +++++ .../space/kscience/kmath/viktor/ViktorBuffer.kt | 2 +- .../space/kscience/kmath/viktor/ViktorFieldOpsND.kt | 2 +- .../space/kscience/kmath/viktor/ViktorStructureND.kt | 2 +- test-utils/src/commonMain/kotlin/AlgebraicVerifier.kt | 2 +- test-utils/src/commonMain/kotlin/FieldVerifier.kt | 2 +- test-utils/src/commonMain/kotlin/RingVerifier.kt | 2 +- test-utils/src/commonMain/kotlin/SpaceVerifier.kt | 2 +- test-utils/src/commonMain/kotlin/asserts.kt | 2 +- 451 files changed, 490 insertions(+), 454 deletions(-) diff --git a/.idea/copyright/kmath.xml b/.idea/copyright/kmath.xml index 17e44e4d0..840e0c87c 100644 --- a/.idea/copyright/kmath.xml +++ b/.idea/copyright/kmath.xml @@ -1,6 +1,7 @@ - - - + + + \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml index b538bdf41..1c10bd6f5 100644 --- a/.idea/copyright/profiles_settings.xml +++ b/.idea/copyright/profiles_settings.xml @@ -1,5 +1,5 @@ - + diff --git a/benchmarks/src/jsMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt b/benchmarks/src/jsMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt index 126a2e648..fd1b4307a 100644 --- a/benchmarks/src/jsMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt +++ b/benchmarks/src/jsMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt index ff933997f..abfc8cbf2 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt index 188a48ca7..19795b9eb 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt index 39819d407..41b9005e4 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt index d7ead6dd8..7cbe83113 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt index db3524e67..4df5f372f 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt index 5d4eee7c0..041f7e92a 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt index 4ff687aac..f7aac8199 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt index eb5e1da47..141d0433b 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/TensorAlgebraBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/TensorAlgebraBenchmark.kt index 38e064e53..3ed7163b3 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/TensorAlgebraBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/TensorAlgebraBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt index 0e92a703e..25ce8410a 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ 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 7bb0b876e..ea417e564 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/globals.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/globals.kt index 9f235c56e..f6d278d83 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/globals.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/globals.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/JmhReport.kt b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/JmhReport.kt index eaa0f59d8..62cf44915 100644 --- a/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/JmhReport.kt +++ b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/JmhReport.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt index 33d186bfc..5c6a2ac83 100644 --- a/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt +++ b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt b/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt index 7c23d8ea0..183510232 100644 --- a/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt +++ b/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/docs/images/KM.svg b/docs/images/KM.svg index 6f80e4d08..55a4339b1 100644 --- a/docs/images/KM.svg +++ b/docs/images/KM.svg @@ -1,6 +1,6 @@ diff --git a/docs/images/KM_mono.svg b/docs/images/KM_mono.svg index 8f8e470b2..f1194f887 100644 --- a/docs/images/KM_mono.svg +++ b/docs/images/KM_mono.svg @@ -1,6 +1,6 @@ diff --git a/docs/images/KMath.svg b/docs/images/KMath.svg index f751d8eb9..509a184bc 100644 --- a/docs/images/KMath.svg +++ b/docs/images/KMath.svg @@ -1,6 +1,6 @@ diff --git a/docs/images/KMath_mono.svg b/docs/images/KMath_mono.svg index 8ca6c5e84..e781979e2 100644 --- a/docs/images/KMath_mono.svg +++ b/docs/images/KMath_mono.svg @@ -1,6 +1,6 @@ diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/astRendering.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/astRendering.kt index c4f263f97..e85bab8d8 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/ast/astRendering.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/astRendering.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt index 907f1bbe4..cacb6683e 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/expressions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt index dec3bfb81..b443e639d 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/kotlingradSupport.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/ast/symjaSupport.kt b/examples/src/main/kotlin/space/kscience/kmath/ast/symjaSupport.kt index 7e09faeff..92ee1781b 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/ast/symjaSupport.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/ast/symjaSupport.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/fit/chiSquared.kt b/examples/src/main/kotlin/space/kscience/kmath/fit/chiSquared.kt index 63e57bd8c..e32b97136 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/fit/chiSquared.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/fit/chiSquared.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/fit/qowFit.kt b/examples/src/main/kotlin/space/kscience/kmath/fit/qowFit.kt index d52976671..73fca8a38 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/fit/qowFit.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/fit/qowFit.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt index 59eaba5bd..28169f15a 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/integrate.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt index 8dbc7b7a4..b4ce6ad2d 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/interpolate.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/interpolateSquare.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/interpolateSquare.kt index a50df0931..7bcd96990 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/interpolateSquare.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/interpolateSquare.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt index 4f99aeb47..1b578626d 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/matrixIntegration.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt index c65ca589d..8228983e2 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/polynomials.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/jafama/JafamaDemo.kt b/examples/src/main/kotlin/space/kscience/kmath/jafama/JafamaDemo.kt index 9c3d0fdbe..52451e9f3 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/jafama/JafamaDemo.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/jafama/JafamaDemo.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/linear/dotPerformance.kt b/examples/src/main/kotlin/space/kscience/kmath/linear/dotPerformance.kt index a2d7d7c27..d9c3281f2 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/linear/dotPerformance.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/linear/dotPerformance.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt b/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt index a01ea7fe2..52ed8f05f 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/linear/gradient.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/operations/BigIntDemo.kt b/examples/src/main/kotlin/space/kscience/kmath/operations/BigIntDemo.kt index 51f439612..2447d06ed 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/operations/BigIntDemo.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/operations/BigIntDemo.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/operations/complexDemo.kt b/examples/src/main/kotlin/space/kscience/kmath/operations/complexDemo.kt index 285b8d000..77cfca4ae 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/operations/complexDemo.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/operations/complexDemo.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/operations/mixedNDOperations.kt b/examples/src/main/kotlin/space/kscience/kmath/operations/mixedNDOperations.kt index 62c9c8076..8fc6e1b06 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/operations/mixedNDOperations.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/operations/mixedNDOperations.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt index 8e3cdf86f..bdbf42797 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt index 15654971f..3de9b6f34 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/ComplexND.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/ComplexND.kt index d55f3df09..86d7c0d89 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/ComplexND.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/ComplexND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt index d6ff1dceb..48d14cb4c 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/NDField.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt index 548fb16c1..aed0a7868 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt index de36c664d..a64ac7280 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt index dea7095a8..ce5301a7b 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureWriteBenchmark.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/buffers.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/buffers.kt index 889ea99bd..2ac0dc6a4 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/buffers.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/buffers.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt b/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt index c28b566b9..1ba0e3503 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/typeSafeDimensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt index b42602988..f7c5bb4b7 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt index aced0cf7d..c4d0ed93e 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/dataSetNormalization.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/dataSetNormalization.kt index a436ae1c3..6d72fd623 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/dataSetNormalization.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/dataSetNormalization.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt index f465fc424..a08fe4106 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/multik.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/multik.kt index 7cf1c5120..67e0631e7 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/multik.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/multik.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt index 5c41ab0f1..cbc83c336 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/TypedMst.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/TypedMst.kt index 8a8b8797d..6458dc123 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/TypedMst.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/TypedMst.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/evaluateConstants.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/evaluateConstants.kt index 71fb154c9..e411cd251 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/evaluateConstants.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/evaluateConstants.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt index 012a6e65f..2c9a2a9ad 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt index 2df3d3cc7..13806703c 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt index 8b5819b84..bd941745b 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt index fdef35ebd..dd8ed3457 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt index ee23ab408..14df5ad8d 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt index 362c07d72..e19a9722e 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt index 90f78a152..c1a895015 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt index 291399cee..dce99cc5a 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt index c0271fbb5..f42237ba6 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt index 1edb5923e..3400db0f8 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerConsistencyWithInterpreter.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt index be8a92f3e..bf56b80a6 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerOperations.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt index 93ef97b0f..f23d36240 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestCompilerVariables.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestFolding.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestFolding.kt index 954a0f330..95b804455 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestFolding.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestFolding.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParser.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParser.kt index d0c3a789e..d3c203903 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParser.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParser.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParserPrecedence.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParserPrecedence.kt index 42cf5ce58..4b3631663 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParserPrecedence.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/TestParserPrecedence.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt index a40c785b9..7b5ec5765 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestFeatures.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt index 43f31baba..66c0ae1ae 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestLatex.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt index 145055494..8bc014c54 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestMathML.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt index 09ec127c7..306538d5d 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestStages.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt index bf87b6fd0..79f178eef 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/rendering/TestUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/utils.kt b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/utils.kt index ec7436188..fe035c69f 100644 --- a/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/utils.kt +++ b/kmath-ast/src/commonTest/kotlin/space/kscience/kmath/ast/utils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt index 521907d2c..f6411334c 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt index 240acf1d7..853f5f983 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt index 16a59d273..1517cdef2 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/ESTreeBuilder.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.typealises.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.typealises.kt index eb5c1e3dd..2434788ec 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.typealises.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/internal/astring/astring.typealises.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.kt index cca2d83af..cc4360f8d 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt index 93b4f6ce6..a17726c9d 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/astring/astring.typealises.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt index 86e0cede7..8ea699837 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/base64/base64.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt index 42b6ac7d8..d907a12c9 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt index 523b13b40..eebfeb6ef 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/binaryen/index.binaryen.typealiases.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/emitter/emitter.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/emitter/emitter.kt index 1f7b09af8..a2a04da79 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/emitter/emitter.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/emitter/emitter.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.extensions.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.extensions.kt index 5b1ce914e..2dd2c08cd 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.extensions.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.extensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.kt index b62b8c06c..bf4a25367 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/estree/estree.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt index 52be5530f..ced165a3a 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/stream/stream.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es2015.iterable.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es2015.iterable.kt index 9c012e3a3..2c0dc9de1 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es2015.iterable.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es2015.iterable.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es5.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es5.kt index 0cd395f2c..f20e2d865 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es5.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/tsstdlib/lib.es5.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt index 90690abed..873a5e1d2 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/lib.dom.WebAssembly.module_dukat.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt index c5023c384..ba86e977b 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/internal/webassembly/nonDeclarations.WebAssembly.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt index 878919d8d..d29fbde55 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt index 21a88b5d0..d60f24247 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/f64StandardFunctions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt index f9540f9db..6a20da799 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt index 0d896c6f6..c6b241e5c 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt index 8ae5fcb36..0a85d5f24 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt index 73b9c97a7..59a26af7d 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt index a76b47ecc..e1fd455fd 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/AsmBuilder.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/GenericAsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/GenericAsmBuilder.kt index 6cf3d8721..acae45d87 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/GenericAsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/GenericAsmBuilder.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/PrimitiveAsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/PrimitiveAsmBuilder.kt index 01bad83e5..d50318cd1 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/PrimitiveAsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/PrimitiveAsmBuilder.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt index 9e880f4fc..b3ccfdc0c 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/codegenUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/mapIntrinsics.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/mapIntrinsics.kt index 3a5ef74f7..6459f4dcf 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/mapIntrinsics.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/mapIntrinsics.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt index 556adbe7d..ec66be830 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt index 47f1cc476..9f0fb33ab 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt index 82694d95a..6d756b15f 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpression.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMGaussRuleIntegrator.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMGaussRuleIntegrator.kt index e0a2f4931..263463d37 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMGaussRuleIntegrator.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMGaussRuleIntegrator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ package space.kscience.kmath.commons.integration diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt index 257429fa7..4839518e6 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt index aa7e0a638..e95c9115d 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt index 9bb5deffd..19799aab3 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMSolver.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizer.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizer.kt index 11eb6fba8..46baa7d50 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizer.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @file:OptIn(UnstableKMathAPI::class) diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt index 194be6002..c7a23ebc4 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/random/CMRandomGeneratorWrapper.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt index 40168971e..2243dc5d9 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/transform/Transformations.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt index 56252ab34..40ba9fc7d 100644 --- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt +++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/expressions/DerivativeStructureExpressionTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt index c5573fef1..308f504af 100644 --- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt +++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt index 0977dc247..b1b7b3ed7 100644 --- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt +++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt index f56fb0f6e..5804e47c1 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ 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 65943f421..42914ed5b 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/ComplexFieldND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt index 0305bfc88..aa5806932 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexBufferSpecTest.kt b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexBufferSpecTest.kt index 17a077ea7..ca3f8f43f 100644 --- a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexBufferSpecTest.kt +++ b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexBufferSpecTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexFieldTest.kt b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexFieldTest.kt index cbaaa815b..e11f1c1ea 100644 --- a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexFieldTest.kt +++ b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexFieldTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexTest.kt b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexTest.kt index 7ad7f883d..1a35d1dd8 100644 --- a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexTest.kt +++ b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ComplexTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt index 4279471d4..767406e0b 100644 --- a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt +++ b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/ExpressionFieldForComplexTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/QuaternionTest.kt b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/QuaternionTest.kt index fd4df736c..fd0fd46a7 100644 --- a/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/QuaternionTest.kt +++ b/kmath-complex/src/commonTest/kotlin/space/kscience/kmath/complex/QuaternionTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt index e06b774fd..d09228e96 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt index 2fce772cc..a3c3a2eda 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYErrorColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYErrorColumnarData.kt index 8ddd6406f..dd0e35bc8 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYErrorColumnarData.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYErrorColumnarData.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt index e99ae0698..3dc1bb99b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain.kt index b5a84cf6c..eecdcebad 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain1D.kt index 3d531349c..10755e633 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain1D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain1D.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/DoubleDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/DoubleDomain.kt index ee1bebde0..b0803f3e1 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/DoubleDomain.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/DoubleDomain.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ package space.kscience.kmath.domains diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt index 485416a69..7d5843a97 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/HyperSquareDomain.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ package space.kscience.kmath.domains diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt index 32a5fc56c..e8b867fac 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ package space.kscience.kmath.domains diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DSAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DSAlgebra.kt index c55e41bb2..fa8bf5e58 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 @@ -1,6 +1,6 @@ /* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + * Copyright 2018-2022 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ package space.kscience.kmath.expressions 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 b5b2988a3..6ab9b3d44 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 @@ -1,6 +1,6 @@ /* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + * Copyright 2018-2022 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ package space.kscience.kmath.expressions diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt index 12b7df0ea..7c8a957c7 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/DifferentiableExpression.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt index 5ba32f190..9c769caa0 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Expression.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt index 68cc8e791..1054d1aa1 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/FunctionalExpressionAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt index 18226119b..9705a3f03 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MST.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt index 4bd2a6c53..a75940cca 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt index ac8c44446..f00e6d3f3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Symbol.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Symbol.kt index 8ab2bec31..c57ce69ab 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Symbol.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/Symbol.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt index bf37e9615..e5f92efc9 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/specialExpressions.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/specialExpressions.kt index 907ce4004..8cfa1b353 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/specialExpressions.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/specialExpressions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt index 8f7569699..361d59be1 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/BufferedLinearSpace.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/DoubleLinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/DoubleLinearSpace.kt index 4e6debc60..e2f81d84e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/DoubleLinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/DoubleLinearSpace.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt index fae9e7c91..af9ebb463 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSolver.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt index d437070c9..757752115 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt index fb57f2343..0ee7c8828 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt index 029612bc5..d0105e4cd 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixFeatures.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixFeatures.kt index b70e9d8a9..ce7acdcba 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixFeatures.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixFeatures.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt index b1812f49d..feea26b40 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt index fb2b1e547..eb5e20856 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/VirtualMatrix.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Featured.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Featured.kt index 29b7caec6..a752a8339 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Featured.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/Featured.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt index 60fa81cd8..f7b486850 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt index ee7f1d8be..6ccb487c3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/logging.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/logging.kt index 9dfc564c3..c7886469f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/logging.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/logging.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/numbers.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/numbers.kt index f879a06d5..77ef07ea8 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/numbers.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/numbers.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/sorting.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/sorting.kt index dc5421136..daf5e1eff 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/sorting.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/sorting.kt @@ -1,6 +1,6 @@ /* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + * Copyright 2018-2022 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt index ad291cf7f..101f90160 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/AlgebraND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ 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 8c5eef3d0..4025ba548 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferAlgebraND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ 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 8175bd65e..5484ce545 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt index d01a8ee95..7f8d3c55d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/DoubleFieldND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ 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 d682d5e69..c5d04c9de 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndexer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndexer.kt index 29701425f..2dce407ca 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndexer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeIndexer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt index 8152adaa5..ea37da7a3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt index 4ccb15eef..2a258a7f4 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure1D.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt index a2fd83474..d8fd2031c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/Structure2D.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ 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 e14b8bf9d..0fed49f40 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ 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 7e86ea73d..579a0d7c8 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/algebraNDExtentions.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/algebraNDExtentions.kt index 53f946fbd..1b7bd20db 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/algebraNDExtentions.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/algebraNDExtentions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/operationsND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/operationsND.kt index c9624dc4e..5814e2f9c 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt index a93b4365e..a7a5bc5fd 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt index 9b6911f73..8730ff163 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ 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 a256fe7d1..3af77856c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BufferAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BufferAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/DoubleBufferField.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/DoubleBufferField.kt index f2f7326aa..449730e7a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/DoubleBufferField.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/DoubleBufferField.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/DoubleBufferOps.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/DoubleBufferOps.kt index 669c0a390..811926c23 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/DoubleBufferOps.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/DoubleBufferOps.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/LogicAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/LogicAlgebra.kt index 9037525e1..5cf98c7d5 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/LogicAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/LogicAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt index d0405c705..5c2747686 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt index 709506fc4..c24394add 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/OptionalOperations.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt index 539440de9..efadfb3cc 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/algebraExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/bufferOperation.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/bufferOperation.kt index 46abc0266..3d25d8750 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/bufferOperation.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/bufferOperation.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt index c108aa729..16088a825 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ArrayBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ArrayBuffer.kt index 3528b0460..8e81dd941 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ArrayBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ArrayBuffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt index 5757848fe..2f9f8a8e0 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt index 4d04a5235..07355d396 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/BufferAccessor2D.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ByteBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ByteBuffer.kt index e7bf2b47c..2be17c5e4 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ByteBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ByteBuffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBuffer.kt index f4388a477..e39c22158 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBuffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FlaggedBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FlaggedBuffer.kt index b3c537280..d99e02996 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FlaggedBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FlaggedBuffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt index e7e98fc71..8666ca675 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/FloatBuffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt index 35b722e2b..8477fc13b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ListBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ListBuffer.kt index 65d9dc77d..fbc9a489b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ListBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ListBuffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt index c69f4646d..9d6f1b2a7 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/LongBuffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MemoryBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MemoryBuffer.kt index 1dadaf7d4..80d5033c4 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MemoryBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MemoryBuffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MutableBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MutableBuffer.kt index 429c1a64b..709ebd680 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MutableBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MutableBuffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt index 20691511b..7dbb2b58e 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/ShortBuffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DSTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/DSTest.kt index b6581e503..f46f3023d 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 @@ -1,6 +1,6 @@ /* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + * Copyright 2018-2022 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @file:OptIn(UnstableKMathAPI::class) diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt index 80c5943cf..def9f91a6 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/ExpressionFieldTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt index 156334b2e..6f207eab3 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt index 201890933..1618296be 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/SimpleAutoDiffTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt index 70e010f2e..25e29f3d6 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt index 25d187bf0..fe5ea3642 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/misc/CumulativeKtTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/misc/CumulativeKtTest.kt index e5f3f337f..811f2e87f 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/misc/CumulativeKtTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/misc/CumulativeKtTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/misc/PermSortTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/misc/PermSortTest.kt index 4a724ac5f..4f3469ea2 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/misc/PermSortTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/misc/PermSortTest.kt @@ -1,6 +1,6 @@ /* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + * Copyright 2018-2022 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ package space.kscience.kmath.misc diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/NdOperationsTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/NdOperationsTest.kt index 25b062b44..e909a2aea 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/NdOperationsTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/nd/NdOperationsTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt index 0527f5252..f4f7b1a51 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConstructorTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConstructorTest.kt index eec3dc3bf..786c68c70 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConstructorTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConstructorTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConversionsTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConversionsTest.kt index 85f368f3e..36f00dc75 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConversionsTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntConversionsTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntOperationsTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntOperationsTest.kt index 26d6af224..8a6116605 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntOperationsTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntOperationsTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/DoubleFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/DoubleFieldTest.kt index 76171fedd..688daa7fe 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/DoubleFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/DoubleFieldTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NDFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NDFieldTest.kt index b7b89d107..566145621 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NDFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NDFieldTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt index d33eb5112..62c4811e8 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/jsMain/kotlin/space/kscience/kmath/misc/numbers.kt b/kmath-core/src/jsMain/kotlin/space/kscience/kmath/misc/numbers.kt index 68a3c995b..e52ea9298 100644 --- a/kmath-core/src/jsMain/kotlin/space/kscience/kmath/misc/numbers.kt +++ b/kmath-core/src/jsMain/kotlin/space/kscience/kmath/misc/numbers.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/jsMain/kotlin/space/kscience/kmath/operations/isInteger.kt b/kmath-core/src/jsMain/kotlin/space/kscience/kmath/operations/isInteger.kt index 24b81322e..3103f5168 100644 --- a/kmath-core/src/jsMain/kotlin/space/kscience/kmath/operations/isInteger.kt +++ b/kmath-core/src/jsMain/kotlin/space/kscience/kmath/operations/isInteger.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/misc/numbersJVM.kt b/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/misc/numbersJVM.kt index 5ba0dbc9b..3780ea1ae 100644 --- a/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/misc/numbersJVM.kt +++ b/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/misc/numbersJVM.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/BigNumbers.kt b/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/BigNumbers.kt index 6e22c2381..584748bd7 100644 --- a/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/BigNumbers.kt +++ b/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/BigNumbers.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/isInteger.kt b/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/isInteger.kt index b2f9b957b..9868daddf 100644 --- a/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/isInteger.kt +++ b/kmath-core/src/jvmMain/kotlin/space/kscience/kmath/operations/isInteger.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/nativeMain/kotlin/space/kscience/kmath/misc/numbers.kt b/kmath-core/src/nativeMain/kotlin/space/kscience/kmath/misc/numbers.kt index 68a3c995b..e52ea9298 100644 --- a/kmath-core/src/nativeMain/kotlin/space/kscience/kmath/misc/numbers.kt +++ b/kmath-core/src/nativeMain/kotlin/space/kscience/kmath/misc/numbers.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-core/src/nativeMain/kotlin/space/kscience/kmath/operations/isInteger.kt b/kmath-core/src/nativeMain/kotlin/space/kscience/kmath/operations/isInteger.kt index b2f9b957b..9868daddf 100644 --- a/kmath-core/src/nativeMain/kotlin/space/kscience/kmath/operations/isInteger.kt +++ b/kmath-core/src/nativeMain/kotlin/space/kscience/kmath/operations/isInteger.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingChain.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingChain.kt index 87aebff61..2e9a15eed 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingChain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingChain.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt index 25e20291e..797d2db4a 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingDoubleChain.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingIntChain.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingIntChain.kt index ac0327d0b..a481156f2 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingIntChain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/BlockingIntChain.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt index 994255e38..ed0283630 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt index 7bf54d50f..77d4203c5 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/flowExtra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/coroutines/coroutinesExtra.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/coroutines/coroutinesExtra.kt index 1f17efe49..3f06693b0 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/coroutines/coroutinesExtra.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/coroutines/coroutinesExtra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/BufferFlow.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/BufferFlow.kt index 4d4493aa4..00c874751 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/BufferFlow.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/BufferFlow.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/RingBuffer.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/RingBuffer.kt index abe1c9df9..2ac8c1eb4 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/RingBuffer.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/streaming/RingBuffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/chains/ChainExt.kt b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/chains/ChainExt.kt index dd6e39071..a62bcc6b8 100644 --- a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/chains/ChainExt.kt +++ b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/chains/ChainExt.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt index 2b9265843..786d32190 100644 --- a/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt +++ b/kmath-coroutines/src/jvmMain/kotlin/space/kscience/kmath/structures/LazyStructureND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-coroutines/src/jvmTest/kotlin/space/kscience/kmath/streaming/BufferFlowTest.kt b/kmath-coroutines/src/jvmTest/kotlin/space/kscience/kmath/streaming/BufferFlowTest.kt index 9b67f7253..c448168e3 100644 --- a/kmath-coroutines/src/jvmTest/kotlin/space/kscience/kmath/streaming/BufferFlowTest.kt +++ b/kmath-coroutines/src/jvmTest/kotlin/space/kscience/kmath/streaming/BufferFlowTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-coroutines/src/jvmTest/kotlin/space/kscience/kmath/streaming/RingBufferTest.kt b/kmath-coroutines/src/jvmTest/kotlin/space/kscience/kmath/streaming/RingBufferTest.kt index 305b97e5d..a6d7f006c 100644 --- a/kmath-coroutines/src/jvmTest/kotlin/space/kscience/kmath/streaming/RingBufferTest.kt +++ b/kmath-coroutines/src/jvmTest/kotlin/space/kscience/kmath/streaming/RingBufferTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt index e57c22834..14677319c 100644 --- a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt +++ b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt index f04536f04..b93114804 100644 --- a/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt +++ b/kmath-dimensions/src/commonMain/kotlin/space/kscience/kmath/dimensions/Wrappers.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-dimensions/src/commonTest/kotlin/space/kscience/dimensions/DMatrixContextTest.kt b/kmath-dimensions/src/commonTest/kotlin/space/kscience/dimensions/DMatrixContextTest.kt index 59260fe73..e2793855b 100644 --- a/kmath-dimensions/src/commonTest/kotlin/space/kscience/dimensions/DMatrixContextTest.kt +++ b/kmath-dimensions/src/commonTest/kotlin/space/kscience/dimensions/DMatrixContextTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-dimensions/src/jsMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt b/kmath-dimensions/src/jsMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt index 610e8b4c0..1ae484228 100644 --- a/kmath-dimensions/src/jsMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt +++ b/kmath-dimensions/src/jsMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-dimensions/src/jvmMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt b/kmath-dimensions/src/jvmMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt index e6d8b3b35..24cfb14e8 100644 --- a/kmath-dimensions/src/jvmMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt +++ b/kmath-dimensions/src/jvmMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-dimensions/src/nativeMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt b/kmath-dimensions/src/nativeMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt index 64edbe935..f5f749c8a 100644 --- a/kmath-dimensions/src/nativeMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt +++ b/kmath-dimensions/src/nativeMain/kotlin/space/kscience/kmath/dimensions/Dimension.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt index 32030dfe3..beb79fc0e 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt index 27fd3fc53..1d70c0e7d 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt index 37995c27e..c4fae9951 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt index aac327a84..5426055b3 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt @@ -1,6 +1,6 @@ /* - * Copyright 2018-2021 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + * Copyright 2018-2022 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ /* This file is generated with buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt */ 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 af6284e5e..e3bff8987 100644 --- a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt +++ b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlMatrixTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlVectorTest.kt b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlVectorTest.kt index 9592bfa6c..7d3ea314b 100644 --- a/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlVectorTest.kt +++ b/kmath-ejml/src/test/kotlin/space/kscience/kmath/ejml/EjmlVectorTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/DoubleVector.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/DoubleVector.kt index 7b9740c35..e607786fb 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/DoubleVector.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/DoubleVector.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt index 671e272ab..c44b1dff0 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/RealMatrix.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt index dc5c58be0..0c18602f1 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/dot.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt index 1926ef02c..6403cf509 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/realND.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/realND.kt index 52362f4b4..2c06b76b7 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/realND.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/realND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/DoubleMatrixTest.kt b/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/DoubleMatrixTest.kt index 4a0e8de1d..89e55c6d4 100644 --- a/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/DoubleMatrixTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/DoubleMatrixTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/DoubleVectorTest.kt b/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/DoubleVectorTest.kt index e77b96c12..a25091ac2 100644 --- a/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/DoubleVectorTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/DoubleVectorTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/GridTest.kt b/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/GridTest.kt index 8fed8d10e..31be9a452 100644 --- a/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/GridTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/GridTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt index 16af7f555..a9f51f7b0 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 1f9bab52c..af84f47f2 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/functionTypes.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/functionTypes.kt index 0e814993c..c2f95f040 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/functionTypes.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/functionTypes.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialConstructors.kt index 2da9ea6f5..4e9791a87 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialConstructors.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialConstructors.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt index c9377a6c1..5effe566a 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt index 9785d7744..603f0503a 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegrator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ package space.kscience.kmath.integration diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt index 778d85e66..4cfed8efe 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/GaussIntegratorRuleFactory.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt index 05e2e5c55..40fe78898 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrand.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt index 1cf15b42f..18c46b83b 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/Integrator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/MultivariateIntegrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/MultivariateIntegrand.kt index 96b81aaa6..53a563086 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/MultivariateIntegrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/MultivariateIntegrand.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt index 7815757aa..7e4ff0f8b 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt index eb88d9ae0..9a8f475c8 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt index 6fd75e6e6..af8c858fa 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt index 2266092a3..52e8991b1 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt index 34d7bcf41..49d7fd1ca 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt index afcb33bd4..a63142be4 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt index 7e0c6cdf2..3051cdd8d 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt index 9d0fe4cc3..c1b1008ae 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt index ef601c941..3b7409e82 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt index 730a455bf..ffab2157c 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt index 19cb77df5..0a3d00e96 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/misc.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/misc.kt index ff67f19d8..61b50f128 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/misc.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/misc.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt index 9f48a15ea..32fc08ae4 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SimpsonIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SimpsonIntegralTest.kt index 9f2d71554..188f8d15f 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SimpsonIntegralTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SimpsonIntegralTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt index afeba0be4..4a15e96c3 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt index 1143036d4..c0ca6c484 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt index 4c7d816d4..851a8ab7d 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Circle2D.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Circle2D.kt index 8623335b9..585843278 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt index a83cb3ac7..d79c6c40e 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt index c1fc74bf1..173ed5688 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt index d4245c744..4ea2aefdf 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Line.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Line.kt index 85bfcdd8f..ee16a7698 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Line.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Line.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/ReferenceFrame.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/ReferenceFrame.kt index a7a28b596..21045e94e 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/ReferenceFrame.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/ReferenceFrame.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/projections.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/projections.kt index 6ffc43739..6950abbdc 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/projections.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/projections.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/rotations3D.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/rotations3D.kt index 67c3666ed..fbe7ae8ee 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/rotations3D.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/rotations3D.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Euclidean2DSpaceTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Euclidean2DSpaceTest.kt index 6b5f474bc..73edc0fc2 100644 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Euclidean2DSpaceTest.kt +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Euclidean2DSpaceTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Euclidean3DSpaceTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Euclidean3DSpaceTest.kt index 0bc91e77e..6e1fa9943 100644 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Euclidean3DSpaceTest.kt +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Euclidean3DSpaceTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/ProjectionAlongTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/ProjectionAlongTest.kt index dfb65a57c..b57a31a75 100644 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/ProjectionAlongTest.kt +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/ProjectionAlongTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/ProjectionOntoLineTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/ProjectionOntoLineTest.kt index 076025110..02f386158 100644 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/ProjectionOntoLineTest.kt +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/ProjectionOntoLineTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt index 89b69d0f2..3ebe9c4b9 100644 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Vector2DTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Vector2DTest.kt index 5e45b4870..211fd4ed0 100644 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Vector2DTest.kt +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Vector2DTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Vector3DTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Vector3DTest.kt index 55bab4775..315a70374 100644 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Vector3DTest.kt +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Vector3DTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/testUtils.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/testUtils.kt index 0f957529d..2a8c0c3c8 100644 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/testUtils.kt +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/testUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt index fe3278026..43ed24c70 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Counter.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt index 12edafd81..a4ae6d935 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram1D.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram1D.kt index 710e4478b..f9ca6a486 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram1D.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram1D.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/HistogramND.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/HistogramND.kt index 68b24db5d..2cefb33a5 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/HistogramND.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/HistogramND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogram1D.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogram1D.kt index e13928394..3c687d2df 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogram1D.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogram1D.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogramGroupND.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogramGroupND.kt index 1ead049e6..36e994bcf 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogramGroupND.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogramGroupND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt b/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt index ca7c2f324..717f9d7a1 100644 --- a/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt +++ b/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/MultivariateHistogramTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/UniformHistogram1DTest.kt b/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/UniformHistogram1DTest.kt index 09bf3939d..fd107f5e8 100644 --- a/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/UniformHistogram1DTest.kt +++ b/kmath-histograms/src/commonTest/kotlin/space/kscience/kmath/histogram/UniformHistogram1DTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramGroup.kt b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramGroup.kt index 6bec01f9b..a7d34ff71 100644 --- a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramGroup.kt +++ b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramGroup.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-histograms/src/jvmTest/kotlin/space/kscience/kmath/histogram/TreeHistogramTest.kt b/kmath-histograms/src/jvmTest/kotlin/space/kscience/kmath/histogram/TreeHistogramTest.kt index 2c56a88a7..77dc189ee 100644 --- a/kmath-histograms/src/jvmTest/kotlin/space/kscience/kmath/histogram/TreeHistogramTest.kt +++ b/kmath-histograms/src/jvmTest/kotlin/space/kscience/kmath/histogram/TreeHistogramTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt index 91d952a76..f9b8287b4 100644 --- a/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt +++ b/kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/KMathJafama.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt b/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt index 504ad693e..85797134f 100644 --- a/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt +++ b/kmath-jupyter/src/main/kotlin/space/kscience/kmath/jupyter/KMathJupyter.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KMathNumber.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KMathNumber.kt index f7858e172..cd35e0c42 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KMathNumber.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KMathNumber.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KotlingradExpression.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KotlingradExpression.kt index 31b8a9286..110572140 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KotlingradExpression.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KotlingradExpression.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/scalarsAdapters.kt b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/scalarsAdapters.kt index 37ce40cab..dd75a704c 100644 --- a/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/scalarsAdapters.kt +++ b/kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/scalarsAdapters.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt index 570d7dd7f..042777c8a 100644 --- a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt +++ b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/Memory.kt b/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/Memory.kt index e8e51e9e2..006d57c5f 100644 --- a/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/Memory.kt +++ b/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/Memory.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/MemorySpec.kt b/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/MemorySpec.kt index 1ee1cf4e2..19bc3bae4 100644 --- a/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/MemorySpec.kt +++ b/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/MemorySpec.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-memory/src/jsMain/kotlin/space/kscience/kmath/memory/DataViewMemory.kt b/kmath-memory/src/jsMain/kotlin/space/kscience/kmath/memory/DataViewMemory.kt index 6153743fc..40ba84c10 100644 --- a/kmath-memory/src/jsMain/kotlin/space/kscience/kmath/memory/DataViewMemory.kt +++ b/kmath-memory/src/jsMain/kotlin/space/kscience/kmath/memory/DataViewMemory.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt b/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt index aef68fd80..84f7ea412 100644 --- a/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt +++ b/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-memory/src/nativeMain/kotlin/space/kscience/kmath/memory/NativeMemory.kt b/kmath-memory/src/nativeMain/kotlin/space/kscience/kmath/memory/NativeMemory.kt index 5146d9689..b224383e4 100644 --- a/kmath-memory/src/nativeMain/kotlin/space/kscience/kmath/memory/NativeMemory.kt +++ b/kmath-memory/src/nativeMain/kotlin/space/kscience/kmath/memory/NativeMemory.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt index dcc1623cc..989ebcd5d 100644 --- a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikFloatAlgebra.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikFloatAlgebra.kt index db251b552..ee194ae24 100644 --- a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikFloatAlgebra.kt +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikFloatAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikIntAlgebra.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikIntAlgebra.kt index 517845939..05b240787 100644 --- a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikIntAlgebra.kt +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikIntAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikLongAlgebra.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikLongAlgebra.kt index 9c6c1af54..e713e556e 100644 --- a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikLongAlgebra.kt +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikLongAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikShortAlgebra.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikShortAlgebra.kt index 5288351b2..6e5ca5882 100644 --- a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikShortAlgebra.kt +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikShortAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensor.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensor.kt index 3ab4b0e3d..38d61e982 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt index f9768ea39..c6266c985 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-multik/src/commonTest/kotlin/space/kscience/kmath/multik/MultikNDTest.kt b/kmath-multik/src/commonTest/kotlin/space/kscience/kmath/multik/MultikNDTest.kt index 8bc43eef2..8ad220221 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt index e29a3f467..f359b9115 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayIterator.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayIterator.kt index d4cad8996..fedad26e0 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayIterator.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayIterator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt index 2a0fdc86c..0a7d15e20 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructure.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt index ceb384f0d..5ecfe30d6 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/arrays.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/arrays.kt index 3ca756600..401c57a7b 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/arrays.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/arrays.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt index 9d30c2027..9f1022fd9 100644 --- a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt +++ b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt index 30d01338f..d1ad746fe 100644 --- a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt +++ b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayStructureTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt index 02602b068..07146625c 100644 --- a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt +++ b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/FunctionOptimization.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/OptimizationBuilder.kt b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/OptimizationBuilder.kt index 416d0195d..d1ceccf1a 100644 --- a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/OptimizationBuilder.kt +++ b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/OptimizationBuilder.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/OptimizationProblem.kt b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/OptimizationProblem.kt index b42be4035..db154be42 100644 --- a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/OptimizationProblem.kt +++ b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/OptimizationProblem.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/Optimizer.kt b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/Optimizer.kt index 78385a99b..41dcbf770 100644 --- a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/Optimizer.kt +++ b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/Optimizer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/QowOptimizer.kt b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/QowOptimizer.kt index babbaf6cd..669860934 100644 --- a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/QowOptimizer.kt +++ b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/QowOptimizer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/XYFit.kt b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/XYFit.kt index 07fea3126..d2182e91f 100644 --- a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/XYFit.kt +++ b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/XYFit.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @file:OptIn(UnstableKMathAPI::class) diff --git a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/logLikelihood.kt b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/logLikelihood.kt index b4cb2f1cf..e0eeb339c 100644 --- a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/logLikelihood.kt +++ b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/logLikelihood.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt index 6a4d1409f..662e8ca74 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt index e4f2b6c37..185782f22 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt index 6ab660b63..3753a93c4 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt index b744afc51..c2fa6b2ec 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index 267bbd91d..eaf5befb1 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt index 0f3c1ced9..4109338fd 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index 6a11eb1bd..7140ba70e 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index 3c1548516..766d9ce98 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt index b40aa4775..80bf6ec53 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/collectionUtils.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/collectionUtils.kt index c9146a493..e294f3533 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/collectionUtils.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/collectionUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt index d74c0e1fb..9cb0ebb3f 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt index a37a1fe39..188240bf7 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt index e95361724..30b1e2fe4 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt index 4f3f6d88e..e7c11f5ea 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt index 76f1c294e..0a251b3b7 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt index ce49088ae..df4afbd12 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt index 9f29cf31a..88424d23c 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt index 487cd9ee1..9dd2bb743 100644 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/AlgebraicStubTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt index 80476050b..054f0dc4c 100644 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledConstructorsTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt index bde1386da..bb30f7742 100644 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt index 6243818b4..637981b66 100644 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/LabeledPolynomialUtilTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt index e7d8dfd8c..5f7e1a95b 100644 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt index 339643d02..48ea89a46 100644 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt index 1815749ce..ad6240fb9 100644 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedConstructorsTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt index ec2e34520..c2f86198c 100644 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt index 82f1e561a..e5d1ddf48 100644 --- a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt +++ b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/NumberedPolynomialUtilTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/BufferUtils.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/BufferUtils.kt index 3297733b1..ab912a464 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModulo.kt index 5bac4cd73..a037dcd18 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/IntModuloUtils.kt index 33fd03aa0..615523873 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/NTMisc.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/NTMisc.kt index ff67f19d8..61b50f128 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt index 19cb77df5..0a3d00e96 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/assertion.kt index 4ef87f736..c70c229ca 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/misc.kt b/kmath-polynomial/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/misc.kt index 93c3f8ea5..66e46c902 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/Distribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/Distribution.kt index 8dbcb3367..cf2fd5b08 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/Distribution.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/Distribution.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/FactorizedDistribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/FactorizedDistribution.kt index 1218f13c5..14f49a35f 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/FactorizedDistribution.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/FactorizedDistribution.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/NormalDistribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/NormalDistribution.kt index cfc6eba04..8a249c340 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/NormalDistribution.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/NormalDistribution.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalErf.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalErf.kt index 25668446c..bb2bfdd09 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalErf.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalErf.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalGamma.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalGamma.kt index 63db1c56f..1ef2ec02c 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalGamma.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalGamma.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalUtils.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalUtils.kt index 71fd15fe6..a80407773 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalUtils.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/internal/InternalUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterExponentialSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterExponentialSampler.kt index 77d29981f..d861fddae 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterExponentialSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterExponentialSampler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt index 993215d41..912bb0fa3 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AhrensDieterMarsagliaTsangGammaSampler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AliasMethodDiscreteSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AliasMethodDiscreteSampler.kt index 5390a2e09..34d1131b4 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AliasMethodDiscreteSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/AliasMethodDiscreteSampler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/BoxMullerSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/BoxMullerSampler.kt index b3c014553..60a8491f2 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/BoxMullerSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/BoxMullerSampler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/GaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/GaussianSampler.kt index 9219df43e..4a4bfdfeb 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/GaussianSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/GaussianSampler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/KempSmallMeanPoissonSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/KempSmallMeanPoissonSampler.kt index 0105731c4..145946b14 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/KempSmallMeanPoissonSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/KempSmallMeanPoissonSampler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/MarsagliaNormalizedGaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/MarsagliaNormalizedGaussianSampler.kt index 0a68e5c88..a8d289d47 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/MarsagliaNormalizedGaussianSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/MarsagliaNormalizedGaussianSampler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/NormalizedGaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/NormalizedGaussianSampler.kt index 83f87e832..3f6797881 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/NormalizedGaussianSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/NormalizedGaussianSampler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/PoissonSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/PoissonSampler.kt index f0f94900e..83480b4ba 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/PoissonSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/PoissonSampler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/ZigguratNormalizedGaussianSampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/ZigguratNormalizedGaussianSampler.kt index b534fdc14..2cd561468 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/ZigguratNormalizedGaussianSampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/samplers/ZigguratNormalizedGaussianSampler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/MCScope.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/MCScope.kt index 0e06fa162..37e6ea13b 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/MCScope.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/MCScope.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Mean.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Mean.kt index aff7d03d9..fb14a95be 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Mean.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Mean.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Median.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Median.kt index c587277f9..87046cd46 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Median.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Median.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt index d4bc36b5b..ac7977659 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomGenerator.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomGenerator.kt index f280a78aa..94b2bfbea 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomGenerator.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomGenerator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt index 1c88922ac..66ade8119 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Sampler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt index 1f442c09b..1e34fa434 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/SamplerAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt index 43cd5b402..d7638ff81 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Statistic.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/UniformDistribution.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/UniformDistribution.kt index 20cc0e802..fa51bb521 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/UniformDistribution.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/UniformDistribution.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/ValueAndErrorField.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/ValueAndErrorField.kt index 5949213e7..38cd5f900 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/ValueAndErrorField.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/ValueAndErrorField.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/RandomSourceGenerator.kt b/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/RandomSourceGenerator.kt index 202a1c8dd..2da9a9e21 100644 --- a/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/RandomSourceGenerator.kt +++ b/kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/RandomSourceGenerator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt index 19c01e099..802f3ac24 100644 --- a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/CommonsDistributionsTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/MCScopeTest.kt b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/MCScopeTest.kt index cca645809..889274c86 100644 --- a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/MCScopeTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/MCScopeTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/SamplerTest.kt b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/SamplerTest.kt index 1dbbf591b..7b76fb4b6 100644 --- a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/SamplerTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/SamplerTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/StatisticTest.kt b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/StatisticTest.kt index 9eb84899c..0db22fef4 100644 --- a/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/StatisticTest.kt +++ b/kmath-stat/src/jvmTest/kotlin/space/kscience/kmath/stat/StatisticTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/SymjaExpression.kt b/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/SymjaExpression.kt index 3067b5efb..0f8014913 100644 --- a/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/SymjaExpression.kt +++ b/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/SymjaExpression.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/adapters.kt b/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/adapters.kt index 30c37c799..92f2474b8 100644 --- a/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/adapters.kt +++ b/kmath-symja/src/main/kotlin/space/kscience/kmath/symja/adapters.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowAlgebra.kt b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowAlgebra.kt index ad7a978a0..fa7050d2a 100644 --- a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowAlgebra.kt +++ b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowAlgebra.kt @@ -1,3 +1,8 @@ +/* + * Copyright 2018-2022 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + package space.kscience.kmath.tensorflow import org.tensorflow.Graph diff --git a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/IntTensorFlowAlgebra.kt b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/IntTensorFlowAlgebra.kt index 084a445e0..01c8054b3 100644 --- a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/IntTensorFlowAlgebra.kt +++ b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/IntTensorFlowAlgebra.kt @@ -1,3 +1,8 @@ +/* + * Copyright 2018-2022 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + package space.kscience.kmath.tensorflow import org.tensorflow.Graph diff --git a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/TensorFlowAlgebra.kt b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/TensorFlowAlgebra.kt index 7185b84d6..c6eaa7266 100644 --- a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/TensorFlowAlgebra.kt +++ b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/TensorFlowAlgebra.kt @@ -1,3 +1,8 @@ +/* + * Copyright 2018-2022 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + package space.kscience.kmath.tensorflow diff --git a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/tfOperations.kt b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/tfOperations.kt index f67c333ce..a0a2ddc80 100644 --- a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/tfOperations.kt +++ b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/tfOperations.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-tensorflow/src/test/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowOps.kt b/kmath-tensorflow/src/test/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowOps.kt index 308469eed..21340a8db 100644 --- a/kmath-tensorflow/src/test/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowOps.kt +++ b/kmath-tensorflow/src/test/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowOps.kt @@ -1,3 +1,8 @@ +/* + * Copyright 2018-2022 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + package space.kscience.kmath.tensorflow import org.junit.jupiter.api.Test diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt index 3ed34ae5e..587096500 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/AnalyticTensorAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt index 0bddc3f9c..07dfd1597 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/Tensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/Tensor.kt index 482bb5244..b328fbeec 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/Tensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/Tensor.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt index 1b11dc54f..dbc42f7c7 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt index 9c492cda1..33effb2d2 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorPartialDivisionAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt index e412ab5bb..e5739359e 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt index 73a89502c..98e6ab430 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt index 8e5116336..e8239caf4 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 63193fe4c..53115d5e5 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensor.kt index e3d7c3d35..ccff9606e 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensor.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt index 19eefc2f8..3de1c9b1a 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/broadcastUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/broadcastUtils.kt index 9d37423e5..ab97903e4 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/broadcastUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/broadcastUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt index a2d445b45..5db311db4 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt index aba6167ce..49d67c205 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt index a5cdb2f47..dad4368c1 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/utils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/utils.kt index 85cc91b1d..8a96d516f 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/utils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorAlgebraExtensions.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorAlgebraExtensions.kt index d8e8df31e..5904e574e 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorAlgebraExtensions.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorAlgebraExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt index 5dc8114dd..968efa468 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt index 6788ae792..67d5f9a96 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt index 1e21379b4..c777273f3 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index 98ee9e3cb..5b226bd5d 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index d808637c7..5e5ef95be 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index bca6e65d0..28c327973 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt index 134342b33..98beed646 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Pose2D.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Pose2D.kt index 1f7c4a52e..901ba5c67 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Pose2D.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Pose2D.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory.kt index 2e97d43b0..620a5fcc1 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/TrajectoryCost.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/TrajectoryCost.kt index 170851c43..3782a9a32 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/TrajectoryCost.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/TrajectoryCost.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/route.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/route.kt index f67ab124d..2e8e43be9 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/Math.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/Math.kt index 7ee68bd92..cc342de75 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 @@ -1,3 +1,8 @@ +/* + * Copyright 2018-2022 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + package space.kscience.kmath.trajectory import space.kscience.kmath.geometry.Vector2D 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 09375a400..6ea48dae6 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-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 c66fa201b..ce8c6c7a5 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 @@ -1,3 +1,8 @@ +/* + * Copyright 2018-2022 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + package space.kscience.kmath.trajectory.segments import space.kscience.kmath.geometry.Circle2D 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 5170c1db5..eff843ae0 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-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 11eaa0fb3..c1a13f4d9 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 @@ -1,3 +1,8 @@ +/* + * Copyright 2018-2022 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + package space.kscience.kmath.trajectory.segments import space.kscience.kmath.geometry.Euclidean2DSpace diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorBuffer.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorBuffer.kt index 4eedcb5ee..90d5ad9a9 100644 --- a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorBuffer.kt +++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorBuffer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ 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 cecbc35b8..493af54c9 100644 --- a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorFieldOpsND.kt +++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorFieldOpsND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt index 25ca3a10e..c9749d41a 100644 --- a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt +++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorStructureND.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/test-utils/src/commonMain/kotlin/AlgebraicVerifier.kt b/test-utils/src/commonMain/kotlin/AlgebraicVerifier.kt index ddd8fc3ea..261e74f5a 100644 --- a/test-utils/src/commonMain/kotlin/AlgebraicVerifier.kt +++ b/test-utils/src/commonMain/kotlin/AlgebraicVerifier.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/test-utils/src/commonMain/kotlin/FieldVerifier.kt b/test-utils/src/commonMain/kotlin/FieldVerifier.kt index f4ca7506b..a03ca0a27 100644 --- a/test-utils/src/commonMain/kotlin/FieldVerifier.kt +++ b/test-utils/src/commonMain/kotlin/FieldVerifier.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/test-utils/src/commonMain/kotlin/RingVerifier.kt b/test-utils/src/commonMain/kotlin/RingVerifier.kt index 14606cb2c..c40075d93 100644 --- a/test-utils/src/commonMain/kotlin/RingVerifier.kt +++ b/test-utils/src/commonMain/kotlin/RingVerifier.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/test-utils/src/commonMain/kotlin/SpaceVerifier.kt b/test-utils/src/commonMain/kotlin/SpaceVerifier.kt index d761a3775..01c02997b 100644 --- a/test-utils/src/commonMain/kotlin/SpaceVerifier.kt +++ b/test-utils/src/commonMain/kotlin/SpaceVerifier.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ diff --git a/test-utils/src/commonMain/kotlin/asserts.kt b/test-utils/src/commonMain/kotlin/asserts.kt index 8e7d1ae23..8ddce517c 100644 --- a/test-utils/src/commonMain/kotlin/asserts.kt +++ b/test-utils/src/commonMain/kotlin/asserts.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 KMath contributors. + * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -- 2.34.1 From 6111c673eec9c96448711fd8b62f6708b16aee64 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 21 Aug 2022 11:39:17 +0300 Subject: [PATCH 172/275] Type-safe angles --- .../space/kscience/kmath/geometry/angles.kt | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/angles.kt diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/angles.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/angles.kt new file mode 100644 index 000000000..e7b0afcda --- /dev/null +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/angles.kt @@ -0,0 +1,79 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.geometry + +import kotlin.jvm.JvmInline +import kotlin.math.PI + +public sealed interface Angle { + public fun toRadians(): Radians + public fun toDegrees(): Degrees + + public operator fun plus(other: Angle): Angle + public operator fun minus(other: Angle): Angle + + public operator fun times(other: Number): Angle + public operator fun div(other: Number): Angle + public operator fun unaryMinus(): Angle +} + +/** + * Type safe radians + */ +@JvmInline +public value class Radians(public val value: Double) : Angle { + override fun toRadians(): Radians = this + override fun toDegrees(): Degrees = Degrees(value * 180 / PI) + + public override fun plus(other: Angle): Radians = Radians(value + other.toRadians().value) + public override fun minus(other: Angle): Radians = Radians(value - other.toRadians().value) + + public override fun times(other: Number): Radians = Radians(value + other.toDouble()) + public override fun div(other: Number): Radians = Radians(value / other.toDouble()) + public override fun unaryMinus(): Radians = Radians(-value) +} + +public fun sin(angle: Angle): Double = kotlin.math.sin(angle.toRadians().value) +public fun cos(angle: Angle): Double = kotlin.math.cos(angle.toRadians().value) +public fun tan(angle: Angle): Double = kotlin.math.tan(angle.toRadians().value) + +public val Number.radians: Radians get() = Radians(toDouble()) + +/** + * Type safe degrees + */ +@JvmInline +public value class Degrees(public val value: Double) : Angle { + override fun toRadians(): Radians = Radians(value * PI / 180) + override fun toDegrees(): Degrees = this + + public override fun plus(other: Angle): Degrees = Degrees(value + other.toDegrees().value) + public override fun minus(other: Angle): Degrees = Degrees(value - other.toDegrees().value) + + public override fun times(other: Number): Degrees = Degrees(value + other.toDouble()) + public override fun div(other: Number): Degrees = Degrees(value / other.toDouble()) + public override fun unaryMinus(): Degrees = Degrees(-value) +} + +public val Number.degrees: Degrees get() = Degrees(toDouble()) + +/** + * A holder class for Pi representation in radians and degrees + */ +public object Pi { + public val radians: Radians = Radians(PI) + public val degrees: Degrees = radians.toDegrees() +} + +public object PiTimes2 { + public val radians: Radians = Radians(2 * PI) + public val degrees: Degrees = radians.toDegrees() +} + +public object PiDiv2 { + public val radians: Radians = Radians(PI / 2) + public val degrees: Degrees = radians.toDegrees() +} \ No newline at end of file -- 2.34.1 From 5af0c91f0a7fca7b7b64039a5574c92a54071e9b Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 21 Aug 2022 11:39:41 +0300 Subject: [PATCH 173/275] Misc --- build.gradle.kts | 2 +- kmath-polynomial/build.gradle.kts | 6 +++--- .../kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt | 4 ---- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index b6e5b0748..28349f1b9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,7 +11,7 @@ allprojects { } group = "space.kscience" - version = "0.3.1-dev-1" + version = "0.3.1-dev-2" } subprojects { diff --git a/kmath-polynomial/build.gradle.kts b/kmath-polynomial/build.gradle.kts index 42b90a70e..c6946878c 100644 --- a/kmath-polynomial/build.gradle.kts +++ b/kmath-polynomial/build.gradle.kts @@ -1,7 +1,7 @@ plugins { - kotlin("multiplatform") - id("space.kscience.gradle.common") - id("space.kscience.gradle.native") + id("space.kscience.gradle.mpp") + // Disable native target to avoid CI crashes +// id("space.kscience.gradle.native") } description = "Polynomials, rational functions, and utilities" diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt index e412ab5bb..292357a71 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 @@ -5,7 +5,6 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.StructureND import space.kscience.kmath.tensors.api.Tensor @@ -18,8 +17,6 @@ import space.kscience.kmath.tensors.core.internal.tensor * Basic linear algebra operations implemented with broadcasting. * For more information: https://pytorch.org/docs/stable/notes/broadcasting.html */ - -@PerformancePitfall public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun StructureND.plus(arg: StructureND): DoubleTensor { @@ -102,6 +99,5 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { * Compute a value using broadcast double tensor algebra */ @UnstableKMathAPI -@PerformancePitfall public fun DoubleTensorAlgebra.withBroadcast(block: BroadcastDoubleTensorAlgebra.() -> R): R = BroadcastDoubleTensorAlgebra.block() \ No newline at end of file -- 2.34.1 From 978de59b7a412a64309e03d879a9fc053ae6c177 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 21 Aug 2022 11:40:02 +0300 Subject: [PATCH 174/275] Add rotations converter to Quaternions --- .../kscience/kmath/complex/Quaternion.kt | 5 + .../kmath/geometry/Euclidean3DSpace.kt | 12 +- .../kscience/kmath/geometry/rotations3D.kt | 105 ++++++++++++++++-- .../kscience/kmath/geometry/RotationTest.kt | 21 +++- .../kmath/functions/labeledConstructors.kt | 16 +-- 5 files changed, 139 insertions(+), 20 deletions(-) diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt index 0305bfc88..643bff696 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt @@ -117,6 +117,11 @@ public val Quaternion.reciprocal: Quaternion return Quaternion(w / norm2, -x / norm2, -y / norm2, -z / norm2) } + +//TODO consider adding a-priory normalized quaternions +/** + * Produce a normalized version of this quaternion + */ public fun Quaternion.normalized(): Quaternion = with(QuaternionField){ this@normalized / norm(this@normalized) } /** 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 c1fc74bf1..3bfd265b6 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 @@ -27,8 +27,9 @@ public interface Vector3D : Point, Vector { override operator fun iterator(): Iterator = listOf(x, y, z).iterator() } -@Suppress("FunctionName") -public fun Vector3D(x: Double, y: Double, z: Double): Vector3D = Vector3DImpl(x, y, z) +public operator fun Vector3D.component1(): Double = x +public operator fun Vector3D.component2(): Double = y +public operator fun Vector3D.component3(): Double = z public fun Buffer.asVector3D(): Vector3D = object : Vector3D { init { @@ -51,6 +52,9 @@ private data class Vector3DImpl( override val z: Double, ) : Vector3D + +public fun Vector3D(x: Double, y: Double, z: Double): Vector3D = Vector3DImpl(x, y, z) + public object Euclidean3DSpace : GeometrySpace, ScaleOperations { override val zero: Vector3D by lazy { Vector3D(0.0, 0.0, 0.0) } @@ -67,4 +71,8 @@ public object Euclidean3DSpace : GeometrySpace, ScaleOperations Quaternion): Vector3D = rotate(vector, QuaternionField.composition()) @@ -113,4 +121,87 @@ public fun Quaternion.Companion.fromRotationMatrix(matrix: Matrix): Quat z = 0.25 * s, ) } +} + +public enum class RotationOrder { + // proper Euler + XZX, + XYX, + YXY, + YZY, + ZYZ, + ZXZ, + + //Tait–Bryan + XZY, + XYZ, + YXZ, + YZX, + ZYX, + ZXY +} + +/** + * Based on https://github.com/mrdoob/three.js/blob/master/src/math/Quaternion.js + */ +public fun Quaternion.Companion.fromEuler( + a: Angle, + b: Angle, + c: Angle, + rotationOrder: RotationOrder, +): Quaternion { + val c1 = cos (a / 2) + val c2 = cos (b / 2) + val c3 = cos (c / 2) + + val s1 = sin (a / 2) + val s2 = sin (b / 2) + val s3 = sin (c / 2) + + return when (rotationOrder) { + + RotationOrder.XYZ -> Quaternion( + c1 * c2 * c3 - s1 * s2 * s3, + s1 * c2 * c3 + c1 * s2 * s3, + c1 * s2 * c3 - s1 * c2 * s3, + c1 * c2 * s3 + s1 * s2 * c3 + ) + + RotationOrder.YXZ -> Quaternion( + c1 * c2 * c3 + s1 * s2 * s3, + s1 * c2 * c3 + c1 * s2 * s3, + c1 * s2 * c3 - s1 * c2 * s3, + c1 * c2 * s3 - s1 * s2 * c3 + ) + + RotationOrder.ZXY -> Quaternion( + c1 * c2 * c3 - s1 * s2 * s3, + s1 * c2 * c3 - c1 * s2 * s3, + c1 * s2 * c3 + s1 * c2 * s3, + c1 * c2 * s3 + s1 * s2 * c3 + ) + + + RotationOrder.ZYX -> Quaternion( + c1 * c2 * c3 + s1 * s2 * s3, + s1 * c2 * c3 - c1 * s2 * s3, + c1 * s2 * c3 + s1 * c2 * s3, + c1 * c2 * s3 - s1 * s2 * c3 + ) + + RotationOrder.YZX -> Quaternion( + c1 * c2 * c3 - s1 * s2 * s3, + s1 * c2 * c3 + c1 * s2 * s3, + c1 * s2 * c3 + s1 * c2 * s3, + c1 * c2 * s3 - s1 * s2 * c3 + ) + + RotationOrder.XZY -> Quaternion( + c1 * c2 * c3 + s1 * s2 * s3, + s1 * c2 * c3 - c1 * s2 * s3, + c1 * s2 * c3 - s1 * c2 * s3, + c1 * c2 * s3 + s1 * s2 * c3 + ) + else -> TODO("Proper Euler rotation orders are not supported yet") + } } \ No newline at end of file diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt index 89b69d0f2..033055c19 100644 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt @@ -7,24 +7,25 @@ package space.kscience.kmath.geometry import space.kscience.kmath.complex.Quaternion import space.kscience.kmath.complex.normalized +import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.testutils.assertBufferEquals import kotlin.test.Test class RotationTest { @Test - fun rotations() = with(Euclidean3DSpace) { + fun differentRotations() = with(Euclidean3DSpace) { val vector = Vector3D(1.0, 1.0, 1.0) val q = Quaternion(1.0, 2.0, -3.0, 4.0).normalized() val rotatedByQ = rotate(vector, q) val matrix = q.toRotationMatrix() - val rotatedByM = rotate(vector,matrix) + val rotatedByM = rotate(vector, matrix) assertBufferEquals(rotatedByQ, rotatedByM, 1e-4) } @Test - fun rotationConversion() { + fun matrixConversion() { val q = Quaternion(1.0, 2.0, -3.0, 4.0).normalized() @@ -32,4 +33,18 @@ class RotationTest { assertBufferEquals(q, Quaternion.fromRotationMatrix(matrix)) } + + @Test + fun fromRotation() { + val q = Quaternion.fromRotation(0.3.radians, Vector3D(1.0, 1.0, 1.0)) + + assertBufferEquals(DoubleBuffer(0.9887711, 0.0862781, 0.0862781, 0.0862781), q) + } + + @Test + fun fromEuler() { + val q = Quaternion.fromEuler(0.1.radians, 0.2.radians, 0.3.radians, RotationOrder.ZXY) + + assertBufferEquals(DoubleBuffer(0.9818562, 0.0342708, 0.1060205, 0.1534393), q) + } } \ No newline at end of file diff --git a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt index d74c0e1fb..082b133a0 100644 --- a/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt +++ b/kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt @@ -470,7 +470,7 @@ public class DSL2LabeledPolynomialBuilder( } private inline fun submit(signature: Map, lazyCoefficient: Ring.() -> C) { - submit(signature, lazyCoefficient, { it + lazyCoefficient() }) + submit(signature, lazyCoefficient) { it + lazyCoefficient() } } private fun submit(signature: Map, coefficient: C) { @@ -478,9 +478,9 @@ public class DSL2LabeledPolynomialBuilder( } // TODO: `@submit` will be resolved differently. Change it to `@C`. - private fun C.submit() = submit(emptyMap(), { this@submit }) + private fun C.submitSelf() = submit(emptyMap()) { this@submitSelf } - private fun Symbol.submit() = submit(mapOf(this to 1u), { one }) + private fun Symbol.submit() = submit(mapOf(this to 1u)) { one } private fun Term.submit(): Submit { submit(signature, coefficient) @@ -490,7 +490,7 @@ public class DSL2LabeledPolynomialBuilder( public object Submit public operator fun C.unaryPlus(): Submit { - submit() + submitSelf() return Submit } @@ -500,12 +500,12 @@ public class DSL2LabeledPolynomialBuilder( } public operator fun C.plus(other: C): Submit { - submit(emptyMap(), { this@plus + other }) + submit(emptyMap()) { this@plus + other } return Submit } public operator fun C.minus(other: C): Submit { - submit(emptyMap(), { this@minus - other }) + submit(emptyMap()) { this@minus - other } return Submit } @@ -541,7 +541,7 @@ public class DSL2LabeledPolynomialBuilder( public operator fun Symbol.plus(other: C): Submit { this.submit() - other.submit() + other.submitSelf() return Submit } @@ -599,7 +599,7 @@ public class DSL2LabeledPolynomialBuilder( public operator fun Term.plus(other: C): Submit { this.submit() - other.submit() + other.submitSelf() return Submit } -- 2.34.1 From ec77cd1fc324df8cfba80272186e3e3c40184522 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 21 Aug 2022 19:17:38 +0300 Subject: [PATCH 175/275] Geometry overhaul --- kmath-dimensions/build.gradle.kts | 3 +- kmath-geometry/build.gradle.kts | 7 +- .../space/kscience/kmath/geometry/Circle2D.kt | 2 +- .../kmath/geometry/Euclidean2DSpace.kt | 61 ++++++++++----- .../kmath/geometry/Euclidean3DSpace.kt | 76 ++++++++++--------- .../kscience/kmath/geometry/GeometrySpace.kt | 3 +- .../space/kscience/kmath/geometry/Line.kt | 9 ++- .../kscience/kmath/geometry/rotations3D.kt | 14 ++-- .../kmath/geometry/Euclidean2DSpaceTest.kt | 40 +++++----- .../kmath/geometry/Euclidean3DSpaceTest.kt | 50 ++++++------ .../kmath/geometry/ProjectionAlongTest.kt | 20 ++--- .../kmath/geometry/ProjectionOntoLineTest.kt | 46 +++++------ .../kscience/kmath/geometry/RotationTest.kt | 4 +- .../kscience/kmath/geometry/Vector2DTest.kt | 2 +- .../kscience/kmath/geometry/Vector3DTest.kt | 2 +- .../kscience/kmath/geometry/testUtils.kt | 4 +- .../kscience/kmath/geometry/lineExtensions.kt | 20 +++++ .../kscience/kmath/trajectory/DubinsPath.kt | 36 ++++----- .../space/kscience/kmath/trajectory/Pose2D.kt | 18 ++--- .../kscience/kmath/trajectory/Trajectory.kt | 10 +-- .../space/kscience/kmath/trajectory/Math.kt | 8 +- .../kmath/trajectory/dubins/DubinsTests.kt | 7 +- .../kmath/trajectory/segments/ArcTests.kt | 8 +- .../kmath/trajectory/segments/CircleTests.kt | 4 +- .../kmath/trajectory/segments/LineTests.kt | 15 ++-- 25 files changed, 260 insertions(+), 209 deletions(-) create mode 100644 kmath-geometry/src/jvmMain/kotlin/space/kscience/kmath/geometry/lineExtensions.kt diff --git a/kmath-dimensions/build.gradle.kts b/kmath-dimensions/build.gradle.kts index ee1950fa8..1c042ab70 100644 --- a/kmath-dimensions/build.gradle.kts +++ b/kmath-dimensions/build.gradle.kts @@ -1,6 +1,5 @@ plugins { - kotlin("multiplatform") - id("space.kscience.gradle.common") + id("space.kscience.gradle.mpp") id("space.kscience.gradle.native") } diff --git a/kmath-geometry/build.gradle.kts b/kmath-geometry/build.gradle.kts index c9d8823bc..c2057bcbe 100644 --- a/kmath-geometry/build.gradle.kts +++ b/kmath-geometry/build.gradle.kts @@ -1,6 +1,5 @@ plugins { - kotlin("multiplatform") - id("space.kscience.gradle.common") + id("space.kscience.gradle.mpp") id("space.kscience.gradle.native") } @@ -10,6 +9,10 @@ kotlin.sourceSets.commonMain { } } +kscience { + withContextReceivers() +} + readme { maturity = space.kscience.gradle.Maturity.PROTOTYPE } diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Circle2D.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Circle2D.kt index 8623335b9..c665ae6bb 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 @@ -11,7 +11,7 @@ import kotlin.math.PI * A circle in 2D space */ public class Circle2D( - public val center: Vector2D, + 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 a83cb3ac7..f622bbb76 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 @@ -6,45 +6,64 @@ package space.kscience.kmath.geometry import space.kscience.kmath.linear.Point +import space.kscience.kmath.operations.Norm import space.kscience.kmath.operations.ScaleOperations -import space.kscience.kmath.operations.invoke +import kotlin.math.pow import kotlin.math.sqrt -public interface Vector2D : Point, Vector { - public val x: Double - public val y: Double +public interface Vector2D : Point, Vector { + public val x: T + public val y: T override val size: Int get() = 2 - override operator fun get(index: Int): Double = when (index) { + override operator fun get(index: Int): T = when (index) { 0 -> x 1 -> y else -> error("Accessing outside of point bounds") } - override operator fun iterator(): Iterator = listOf(x, y).iterator() + override operator fun iterator(): Iterator = iterator { + yield(x) + yield(y) + } } -public val Vector2D.r: Double - get() = Euclidean2DSpace { norm() } -public fun Vector2D(x: Double, y: Double): Vector2D = Vector2DImpl(x, y) +public operator fun Vector2D.component1(): T = x +public operator fun Vector2D.component2(): T = y + +public typealias DoubleVector2D = Vector2D + +public val Vector2D.r: Double get() = Euclidean2DSpace.norm(this) -private data class Vector2DImpl( - override val x: Double, - override val y: Double, -) : Vector2D /** * 2D Euclidean space */ -public object Euclidean2DSpace : GeometrySpace, ScaleOperations { - override val zero: Vector2D by lazy { Vector2D(0.0, 0.0) } +public object Euclidean2DSpace : GeometrySpace, + ScaleOperations, + Norm { - public fun Vector2D.norm(): Double = sqrt(x * x + y * y) - override fun Vector2D.unaryMinus(): Vector2D = Vector2D(-x, -y) + private data class Vector2DImpl( + override val x: Double, + override val y: Double, + ) : DoubleVector2D - override fun Vector2D.distanceTo(other: Vector2D): Double = (this - other).norm() - override fun add(left: Vector2D, right: Vector2D): Vector2D = Vector2D(left.x + right.x, left.y + right.y) - override fun scale(a: Vector2D, value: Double): Vector2D = Vector2D(a.x * value, a.y * value) - override fun Vector2D.dot(other: Vector2D): Double = x * other.x + y * other.y + public fun vector(x: Number, y: Number): DoubleVector2D = Vector2DImpl(x.toDouble(), y.toDouble()) + + override val zero: DoubleVector2D by lazy { vector(0.0, 0.0) } + + override fun norm(arg: DoubleVector2D): Double = sqrt(arg.x.pow(2) + arg.y.pow(2)) + + override fun DoubleVector2D.unaryMinus(): DoubleVector2D = vector(-x, -y) + + override fun DoubleVector2D.distanceTo(other: DoubleVector2D): Double = norm(this - other) + override fun add(left: DoubleVector2D, right: DoubleVector2D): DoubleVector2D = + vector(left.x + right.x, left.y + right.y) + + override fun scale(a: DoubleVector2D, value: Double): DoubleVector2D = vector(a.x * value, a.y * value) + override fun DoubleVector2D.dot(other: DoubleVector2D): Double = x * other.x + y * other.y + + public val xAxis: DoubleVector2D = vector(1.0, 0.0) + public val yAxis: DoubleVector2D = vector(0.0, 1.0) } diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt index 3bfd265b6..93be2df52 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 @@ -6,73 +6,79 @@ package space.kscience.kmath.geometry import space.kscience.kmath.linear.Point +import space.kscience.kmath.operations.Norm import space.kscience.kmath.operations.ScaleOperations -import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.Buffer +import kotlin.math.pow import kotlin.math.sqrt -public interface Vector3D : Point, Vector { - public val x: Double - public val y: Double - public val z: Double +public interface Vector3D : Point, Vector { + public val x: T + public val y: T + public val z: T override val size: Int get() = 3 - override operator fun get(index: Int): Double = when (index) { + override operator fun get(index: Int): T = when (index) { 0 -> x 1 -> y 2 -> z else -> error("Accessing outside of point bounds") } - override operator fun iterator(): Iterator = listOf(x, y, z).iterator() + override operator fun iterator(): Iterator = listOf(x, y, z).iterator() } -public operator fun Vector3D.component1(): Double = x -public operator fun Vector3D.component2(): Double = y -public operator fun Vector3D.component3(): Double = z +public operator fun Vector3D.component1(): T = x +public operator fun Vector3D.component2(): T = y +public operator fun Vector3D.component3(): T = z -public fun Buffer.asVector3D(): Vector3D = object : Vector3D { +public fun Buffer.asVector3D(): Vector3D = object : Vector3D { init { require(this@asVector3D.size == 3) { "Buffer of size 3 is required for Vector3D" } } - override val x: Double get() = this@asVector3D[0] - override val y: Double get() = this@asVector3D[1] - override val z: Double get() = this@asVector3D[2] + override val x: T get() = this@asVector3D[0] + override val y: T get() = this@asVector3D[1] + override val z: T get() = this@asVector3D[2] override fun toString(): String = this@asVector3D.toString() - } -public val Vector3D.r: Double get() = Euclidean3DSpace { norm() } +public typealias DoubleVector3D = Vector3D -private data class Vector3DImpl( - override val x: Double, - override val y: Double, - override val z: Double, -) : Vector3D +public val DoubleVector3D.r: Double get() = Euclidean3DSpace.norm(this) +public object Euclidean3DSpace : GeometrySpace, ScaleOperations, + Norm { + private data class Vector3DImpl( + override val x: Double, + override val y: Double, + override val z: Double, + ) : DoubleVector3D -public fun Vector3D(x: Double, y: Double, z: Double): Vector3D = Vector3DImpl(x, y, z) + public fun vector(x: Number, y: Number, z: Number): DoubleVector3D = + Vector3DImpl(x.toDouble(), y.toDouble(), z.toDouble()) -public object Euclidean3DSpace : GeometrySpace, ScaleOperations { - override val zero: Vector3D by lazy { Vector3D(0.0, 0.0, 0.0) } + override val zero: DoubleVector3D by lazy { vector(0.0, 0.0, 0.0) } - public fun Vector3D.norm(): Double = sqrt(x * x + y * y + z * z) - override fun Vector3D.unaryMinus(): Vector3D = Vector3D(-x, -y, -z) + override fun norm(arg: DoubleVector3D): Double = sqrt(arg.x.pow(2) + arg.y.pow(2) + arg.z.pow(2)) - override fun Vector3D.distanceTo(other: Vector3D): Double = (this - other).norm() + public fun DoubleVector3D.norm(): Double = norm(this) - override fun add(left: Vector3D, right: Vector3D): Vector3D = - Vector3D(left.x + right.x, left.y + right.y, left.z + right.z) + override fun DoubleVector3D.unaryMinus(): DoubleVector3D = vector(-x, -y, -z) - override fun scale(a: Vector3D, value: Double): Vector3D = - Vector3D(a.x * value, a.y * value, a.z * value) + override fun DoubleVector3D.distanceTo(other: DoubleVector3D): Double = (this - other).norm() - override fun Vector3D.dot(other: Vector3D): Double = + override fun add(left: DoubleVector3D, right: DoubleVector3D): DoubleVector3D = + vector(left.x + right.x, left.y + right.y, left.z + right.z) + + override fun scale(a: DoubleVector3D, value: Double): DoubleVector3D = + vector(a.x * value, a.y * value, a.z * value) + + override fun DoubleVector3D.dot(other: DoubleVector3D): Double = x * other.x + y * other.y + z * other.z - public val xAxis: Vector3D = Vector3D(1.0, 0.0, 0.0) - public val yAxis: Vector3D = Vector3D(0.0, 1.0, 0.0) - public val zAxis: Vector3D = Vector3D(0.0, 0.0, 1.0) + public val xAxis: DoubleVector3D = vector(1.0, 0.0, 0.0) + public val yAxis: DoubleVector3D = vector(0.0, 1.0, 0.0) + public val zAxis: DoubleVector3D = vector(0.0, 0.0, 1.0) } diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt index d4245c744..b06ff9989 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 @@ -6,11 +6,12 @@ package space.kscience.kmath.geometry import space.kscience.kmath.operations.Group +import space.kscience.kmath.operations.Norm import space.kscience.kmath.operations.ScaleOperations public interface Vector -public interface GeometrySpace : Group, ScaleOperations { +public interface GeometrySpace : Group, ScaleOperations, Norm { /** * L2 distance */ diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Line.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Line.kt index 85bfcdd8f..2251af600 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 @@ -11,5 +11,10 @@ package space.kscience.kmath.geometry */ public data class Line(val base: V, val direction: V) -public typealias Line2D = Line -public typealias Line3D = Line +public typealias Line2D = Line +public typealias Line3D = Line + +/** + * A directed line segment between [begin] and [end] + */ +public data class LineSegment(val begin: V, val end: V) diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/rotations3D.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/rotations3D.kt index c0d90463a..2500c78d6 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/rotations3D.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/rotations3D.kt @@ -15,7 +15,7 @@ import space.kscience.kmath.operations.DoubleField import kotlin.math.pow import kotlin.math.sqrt -internal fun Vector3D.toQuaternion(): Quaternion = Quaternion(0.0, x, y, z) +internal fun DoubleVector3D.toQuaternion(): Quaternion = Quaternion(0.0, x, y, z) /** * Angle in radians denoted by this quaternion rotation @@ -25,7 +25,7 @@ public val Quaternion.theta: Radians get() = (kotlin.math.acos(normalized().w) * /** * Create a normalized Quaternion from rotation angle and rotation vector */ -public fun Quaternion.Companion.fromRotation(theta: Angle, vector: Vector3D): Quaternion { +public fun Quaternion.Companion.fromRotation(theta: Angle, vector: DoubleVector3D): Quaternion { val s = sin(theta / 2) val c = cos(theta / 2) val norm = with(Euclidean3DSpace) { vector.norm() } @@ -35,9 +35,9 @@ public fun Quaternion.Companion.fromRotation(theta: Angle, vector: Vector3D): Qu /** * An axis of quaternion rotation */ -public val Quaternion.vector: Vector3D +public val Quaternion.vector: DoubleVector3D get() { - return object : Vector3D { + return object : DoubleVector3D { private val sint2 = sqrt(1 - w * w) override val x: Double get() = this@vector.x / sint2 override val y: Double get() = this@vector.y / sint2 @@ -49,7 +49,7 @@ public val Quaternion.vector: Vector3D /** * Rotate a vector in a [Euclidean3DSpace] */ -public fun Euclidean3DSpace.rotate(vector: Vector3D, q: Quaternion): Vector3D = with(QuaternionField) { +public fun Euclidean3DSpace.rotate(vector: DoubleVector3D, q: Quaternion): DoubleVector3D = with(QuaternionField) { val p = vector.toQuaternion() (q * p * q.reciprocal).vector } @@ -58,10 +58,10 @@ public fun Euclidean3DSpace.rotate(vector: Vector3D, q: Quaternion): Vector3D = * Use a composition of quaternions to create a rotation */ @UnstableKMathAPI -public fun Euclidean3DSpace.rotate(vector: Vector3D, composition: QuaternionField.() -> Quaternion): Vector3D = +public fun Euclidean3DSpace.rotate(vector: DoubleVector3D, composition: QuaternionField.() -> Quaternion): DoubleVector3D = rotate(vector, QuaternionField.composition()) -public fun Euclidean3DSpace.rotate(vector: Vector3D, matrix: Matrix): Vector3D { +public fun Euclidean3DSpace.rotate(vector: DoubleVector3D, matrix: Matrix): DoubleVector3D { require(matrix.colNum == 3 && matrix.rowNum == 3) { "Square 3x3 rotation matrix is required" } return with(DoubleField.linearSpace) { matrix.dot(vector).asVector3D() } } diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Euclidean2DSpaceTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Euclidean2DSpaceTest.kt index 6b5f474bc..8ca6ba248 100644 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Euclidean2DSpaceTest.kt +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Euclidean2DSpaceTest.kt @@ -12,16 +12,16 @@ import kotlin.test.assertEquals internal class Euclidean2DSpaceTest { @Test fun zero() { - assertVectorEquals(Vector2D(0.0, 0.0), Euclidean2DSpace.zero) + assertVectorEquals(Euclidean2DSpace.vector(0.0, 0.0), Euclidean2DSpace.zero) } @Test fun norm() { with(Euclidean2DSpace) { - assertEquals(0.0, zero.norm()) - assertEquals(1.0, Vector2D(1.0, 0.0).norm()) - assertEquals(sqrt(2.0), Vector2D(1.0, 1.0).norm()) - assertEquals(sqrt(5.002001), Vector2D(-2.0, 1.001).norm()) + assertEquals(0.0, norm(zero)) + assertEquals(1.0, norm(vector(1.0, 0.0))) + assertEquals(sqrt(2.0), norm(vector(1.0, 1.0))) + assertEquals(sqrt(5.002001), norm(vector(-2.0, 1.001))) } } @@ -29,16 +29,16 @@ internal class Euclidean2DSpaceTest { fun dotProduct() { with(Euclidean2DSpace) { assertEquals(0.0, zero dot zero) - assertEquals(0.0, zero dot Vector2D(1.0, 0.0)) - assertEquals(0.0, Vector2D(-2.0, 0.001) dot zero) - assertEquals(0.0, Vector2D(1.0, 0.0) dot Vector2D(0.0, 1.0)) + assertEquals(0.0, zero dot vector(1.0, 0.0)) + assertEquals(0.0, vector(-2.0, 0.001) dot zero) + assertEquals(0.0, vector(1.0, 0.0) dot vector(0.0, 1.0)) - assertEquals(1.0, Vector2D(1.0, 0.0) dot Vector2D(1.0, 0.0)) - assertEquals(-2.0, Vector2D(0.0, 1.0) dot Vector2D(1.0, -2.0)) - assertEquals(2.0, Vector2D(1.0, 1.0) dot Vector2D(1.0, 1.0)) - assertEquals(4.001001, Vector2D(-2.0, 1.001) dot Vector2D(-2.0, 0.001)) + assertEquals(1.0, vector(1.0, 0.0) dot vector(1.0, 0.0)) + assertEquals(-2.0, vector(0.0, 1.0) dot vector(1.0, -2.0)) + assertEquals(2.0, vector(1.0, 1.0) dot vector(1.0, 1.0)) + assertEquals(4.001001, vector(-2.0, 1.001) dot vector(-2.0, 0.001)) - assertEquals(-4.998, Vector2D(1.0, 2.0) dot Vector2D(-5.0, 0.001)) + assertEquals(-4.998, vector(1.0, 2.0) dot vector(-5.0, 0.001)) } } @@ -46,12 +46,12 @@ internal class Euclidean2DSpaceTest { fun add() { with(Euclidean2DSpace) { assertVectorEquals( - Vector2D(-2.0, 0.001), - Vector2D(-2.0, 0.001) + zero + vector(-2.0, 0.001), + vector(-2.0, 0.001) + zero ) assertVectorEquals( - Vector2D(-3.0, 3.001), - Vector2D(2.0, 3.0) + Vector2D(-5.0, 0.001) + vector(-3.0, 3.001), + vector(2.0, 3.0) + vector(-5.0, 0.001) ) } } @@ -59,9 +59,9 @@ internal class Euclidean2DSpaceTest { @Test fun multiply() { with(Euclidean2DSpace) { - assertVectorEquals(Vector2D(-4.0, 0.0), Vector2D(-2.0, 0.0) * 2) - assertVectorEquals(Vector2D(4.0, 0.0), Vector2D(-2.0, 0.0) * -2) - assertVectorEquals(Vector2D(300.0, 0.0003), Vector2D(100.0, 0.0001) * 3) + assertVectorEquals(vector(-4.0, 0.0), vector(-2.0, 0.0) * 2) + assertVectorEquals(vector(4.0, 0.0), vector(-2.0, 0.0) * -2) + assertVectorEquals(vector(300.0, 0.0003), vector(100.0, 0.0001) * 3) } } } diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Euclidean3DSpaceTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Euclidean3DSpaceTest.kt index 0bc91e77e..191ba54ab 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 @@ -11,21 +11,21 @@ import kotlin.test.assertEquals internal class Euclidean3DSpaceTest { @Test fun zero() { - assertVectorEquals(Vector3D(0.0, 0.0, 0.0), Euclidean3DSpace.zero) + assertVectorEquals(Euclidean3DSpace.vector(0.0, 0.0, 0.0), Euclidean3DSpace.zero) } @Test fun distance() { with(Euclidean3DSpace) { assertEquals(0.0, zero.distanceTo(zero)) - assertEquals(1.0, zero.distanceTo(Vector3D(1.0, 0.0, 0.0))) - assertEquals(kotlin.math.sqrt(5.000001), Vector3D(1.0, -2.0, 0.001).distanceTo(zero)) - assertEquals(0.0, Vector3D(1.0, -2.0, 0.001).distanceTo(Vector3D(1.0, -2.0, 0.001))) - assertEquals(0.0, Vector3D(1.0, 0.0, 0.0).distanceTo(Vector3D(1.0, 0.0, 0.0))) - assertEquals(kotlin.math.sqrt(2.0), Vector3D(1.0, 0.0, 0.0).distanceTo(Vector3D(1.0, 1.0, 1.0))) - assertEquals(3.1622778182822584, Vector3D(0.0, 1.0, 0.0).distanceTo(Vector3D(1.0, -2.0, 0.001))) - assertEquals(0.0, Vector3D(1.0, -2.0, 0.001).distanceTo(Vector3D(1.0, -2.0, 0.001))) - assertEquals(9.695050335093676, Vector3D(1.0, 2.0, 3.0).distanceTo(Vector3D(7.0, -5.0, 0.001))) + assertEquals(1.0, zero.distanceTo(vector(1.0, 0.0, 0.0))) + assertEquals(kotlin.math.sqrt(5.000001), vector(1.0, -2.0, 0.001).distanceTo(zero)) + assertEquals(0.0, vector(1.0, -2.0, 0.001).distanceTo(vector(1.0, -2.0, 0.001))) + assertEquals(0.0, vector(1.0, 0.0, 0.0).distanceTo(vector(1.0, 0.0, 0.0))) + assertEquals(kotlin.math.sqrt(2.0), vector(1.0, 0.0, 0.0).distanceTo(vector(1.0, 1.0, 1.0))) + assertEquals(3.1622778182822584, vector(0.0, 1.0, 0.0).distanceTo(vector(1.0, -2.0, 0.001))) + assertEquals(0.0, vector(1.0, -2.0, 0.001).distanceTo(vector(1.0, -2.0, 0.001))) + assertEquals(9.695050335093676, vector(1.0, 2.0, 3.0).distanceTo(vector(7.0, -5.0, 0.001))) } } @@ -33,9 +33,9 @@ internal class Euclidean3DSpaceTest { fun norm() { with(Euclidean3DSpace) { assertEquals(0.0, zero.norm()) - assertEquals(1.0, Vector3D(1.0, 0.0, 0.0).norm()) - assertEquals(kotlin.math.sqrt(3.0), Vector3D(1.0, 1.0, 1.0).norm()) - assertEquals(kotlin.math.sqrt(5.000001), Vector3D(1.0, -2.0, 0.001).norm()) + assertEquals(1.0, vector(1.0, 0.0, 0.0).norm()) + assertEquals(kotlin.math.sqrt(3.0), vector(1.0, 1.0, 1.0).norm()) + assertEquals(kotlin.math.sqrt(5.000001), vector(1.0, -2.0, 0.001).norm()) } } @@ -43,16 +43,16 @@ internal class Euclidean3DSpaceTest { fun dotProduct() { with(Euclidean3DSpace) { assertEquals(0.0, zero dot zero) - assertEquals(0.0, zero dot Vector3D(1.0, 0.0, 0.0)) - assertEquals(0.0, Vector3D(1.0, -2.0, 0.001) dot zero) + assertEquals(0.0, zero dot vector(1.0, 0.0, 0.0)) + assertEquals(0.0, vector(1.0, -2.0, 0.001) dot zero) - assertEquals(1.0, Vector3D(1.0, 0.0, 0.0) dot Vector3D(1.0, 0.0, 0.0)) - assertEquals(1.0, Vector3D(1.0, 0.0, 0.0) dot Vector3D(1.0, 1.0, 1.0)) - assertEquals(-2.0, Vector3D(0.0, 1.0, 0.0) dot Vector3D(1.0, -2.0, 0.001)) - assertEquals(3.0, Vector3D(1.0, 1.0, 1.0) dot Vector3D(1.0, 1.0, 1.0)) - assertEquals(5.000001, Vector3D(1.0, -2.0, 0.001) dot Vector3D(1.0, -2.0, 0.001)) + assertEquals(1.0, vector(1.0, 0.0, 0.0) dot vector(1.0, 0.0, 0.0)) + assertEquals(1.0, vector(1.0, 0.0, 0.0) dot vector(1.0, 1.0, 1.0)) + assertEquals(-2.0, vector(0.0, 1.0, 0.0) dot vector(1.0, -2.0, 0.001)) + assertEquals(3.0, vector(1.0, 1.0, 1.0) dot vector(1.0, 1.0, 1.0)) + assertEquals(5.000001, vector(1.0, -2.0, 0.001) dot vector(1.0, -2.0, 0.001)) - assertEquals(-2.997, Vector3D(1.0, 2.0, 3.0) dot Vector3D(7.0, -5.0, 0.001)) + assertEquals(-2.997, vector(1.0, 2.0, 3.0) dot vector(7.0, -5.0, 0.001)) } } @@ -60,12 +60,12 @@ internal class Euclidean3DSpaceTest { fun add() { with(Euclidean3DSpace) { assertVectorEquals( - Vector3D(1.0, -2.0, 0.001), - Vector3D(1.0, -2.0, 0.001) + zero + vector(1.0, -2.0, 0.001), + vector(1.0, -2.0, 0.001) + zero ) assertVectorEquals( - Vector3D(8.0, -3.0, 3.001), - Vector3D(1.0, 2.0, 3.0) + Vector3D(7.0, -5.0, 0.001) + vector(8.0, -3.0, 3.001), + vector(1.0, 2.0, 3.0) + vector(7.0, -5.0, 0.001) ) } } @@ -73,7 +73,7 @@ internal class Euclidean3DSpaceTest { @Test fun multiply() { with(Euclidean3DSpace) { - assertVectorEquals(Vector3D(2.0, -4.0, 0.0), Vector3D(1.0, -2.0, 0.0) * 2) + assertVectorEquals(vector(2.0, -4.0, 0.0), vector(1.0, -2.0, 0.0) * 2) } } } diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/ProjectionAlongTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/ProjectionAlongTest.kt index dfb65a57c..cebbf5a4d 100644 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/ProjectionAlongTest.kt +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/ProjectionAlongTest.kt @@ -12,14 +12,14 @@ internal class ProjectionAlongTest { @Test fun projectionIntoYEqualsX() { with(Euclidean2DSpace) { - val normal = Vector2D(-2.0, 2.0) - val base = Vector2D(2.3, 2.3) + val normal = vector(-2.0, 2.0) + val base = vector(2.3, 2.3) assertVectorEquals(zero, projectAlong(zero, normal, base)) grid(-10.0..10.0, -10.0..10.0, 0.15).forEach { (x, y) -> val d = (y - x) / 2.0 - assertVectorEquals(Vector2D(x + d, y - d), projectAlong(Vector2D(x, y), normal, base)) + assertVectorEquals(vector(x + d, y - d), projectAlong(vector(x, y), normal, base)) } } } @@ -30,28 +30,28 @@ internal class ProjectionAlongTest { val a = 5.0 val b = -3.0 val c = -15.0 - val normal = Vector2D(-5.0, 3.0) - val base = Vector2D(3.0, 0.0) + val normal = vector(-5.0, 3.0) + val base = vector(3.0, 0.0) grid(-10.0..10.0, -10.0..10.0, 0.15).forEach { (x, y) -> val xProj = (b * (b * x - a * y) - a * c) / (a * a + b * b) val yProj = (a * (-b * x + a * y) - b * c) / (a * a + b * b) - assertVectorEquals(Vector2D(xProj, yProj), projectAlong(Vector2D(x, y), normal, base)) + assertVectorEquals(vector(xProj, yProj), projectAlong(vector(x, y), normal, base)) } } } @Test - fun projectOntoPlane() { - val normal = Vector3D(1.0, 3.5, 0.07) - val base = Vector3D(2.0, -0.0037, 11.1111) + fun projectOntoPlane() = with(Euclidean3DSpace){ + val normal = vector(1.0, 3.5, 0.07) + val base = vector(2.0, -0.0037, 11.1111) with(Euclidean3DSpace) { val testDomain = (-10.0..10.0).generateList(0.43) for (x in testDomain) { for (y in testDomain) { for (z in testDomain) { - val v = Vector3D(x, y, z) + val v = vector(x, y, z) val result = projectAlong(v, normal, base) // assert that result is on plane diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/ProjectionOntoLineTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/ProjectionOntoLineTest.kt index 076025110..2ca0b5f76 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 @@ -12,10 +12,10 @@ internal class ProjectionOntoLineTest { @Test fun projectionIntoOx() { with(Euclidean2DSpace) { - val ox = Line(zero, Vector2D(1.0, 0.0)) + val ox = Line(zero, vector(1.0, 0.0)) grid(-10.0..10.0, -10.0..10.0, 0.15).forEach { (x, y) -> - assertVectorEquals(Vector2D(x, 0.0), projectToLine(Vector2D(x, y), ox)) + assertVectorEquals(vector(x, 0.0), projectToLine(vector(x, y), ox)) } } } @@ -23,10 +23,10 @@ internal class ProjectionOntoLineTest { @Test fun projectionIntoOy() { with(Euclidean2DSpace) { - val line = Line(zero, Vector2D(0.0, 1.0)) + val line = Line(zero, vector(0.0, 1.0)) grid(-10.0..10.0, -10.0..10.0, 0.15).forEach { (x, y) -> - assertVectorEquals(Vector2D(0.0, y), projectToLine(Vector2D(x, y), line)) + assertVectorEquals(vector(0.0, y), projectToLine(vector(x, y), line)) } } } @@ -34,13 +34,13 @@ internal class ProjectionOntoLineTest { @Test fun projectionIntoYEqualsX() { with(Euclidean2DSpace) { - val line = Line(zero, Vector2D(1.0, 1.0)) + val line = Line(zero, vector(1.0, 1.0)) assertVectorEquals(zero, projectToLine(zero, line)) grid(-10.0..10.0, -10.0..10.0, 0.15).forEach { (x, y) -> val d = (y - x) / 2.0 - assertVectorEquals(Vector2D(x + d, y - d), projectToLine(Vector2D(x, y), line)) + assertVectorEquals(vector(x + d, y - d), projectToLine(vector(x, y), line)) } } } @@ -51,38 +51,38 @@ internal class ProjectionOntoLineTest { val a = 5.0 val b = -3.0 val c = -15.0 - val line = Line(Vector2D(3.0, 0.0), Vector2D(3.0, 5.0)) + val line = Line(vector(3.0, 0.0), vector(3.0, 5.0)) grid(-10.0..10.0, -10.0..10.0, 0.15).forEach { (x, y) -> val xProj = (b * (b * x - a * y) - a * c) / (a * a + b * b) val yProj = (a * (-b * x + a * y) - b * c) / (a * a + b * b) - assertVectorEquals(Vector2D(xProj, yProj), projectToLine(Vector2D(x, y), line)) + assertVectorEquals(vector(xProj, yProj), projectToLine(vector(x, y), line)) } } } @Test - fun projectionOntoLine3d() { + fun projectionOntoLine3d() = with(Euclidean3DSpace) { val line = Line3D( - base = Vector3D(1.0, 3.5, 0.07), - direction = Vector3D(2.0, -0.0037, 11.1111) + base = vector(1.0, 3.5, 0.07), + direction = vector(2.0, -0.0037, 11.1111) ) - with(Euclidean3DSpace) { - val testDomain = (-10.0..10.0).generateList(0.43) - for (x in testDomain) { - for (y in testDomain) { - for (z in testDomain) { - val v = Vector3D(x, y, z) - val result = projectToLine(v, line) - // assert that result is on line - assertTrue(isCollinear(result - line.base, line.direction)) - // assert that PV vector is orthogonal to direction vector - assertTrue(isOrthogonal(v - result, line.direction)) - } + val testDomain = (-10.0..10.0).generateList(0.43) + for (x in testDomain) { + for (y in testDomain) { + for (z in testDomain) { + val v = vector(x, y, z) + val result = projectToLine(v, line) + + // assert that result is on the line + assertTrue(isCollinear(result - line.base, line.direction)) + // assert that PV vector is orthogonal to direction vector + assertTrue(isOrthogonal(v - result, line.direction)) } } } + } } diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt index 033055c19..8febe6722 100644 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/RotationTest.kt @@ -15,7 +15,7 @@ class RotationTest { @Test fun differentRotations() = with(Euclidean3DSpace) { - val vector = Vector3D(1.0, 1.0, 1.0) + val vector = vector(1.0, 1.0, 1.0) val q = Quaternion(1.0, 2.0, -3.0, 4.0).normalized() val rotatedByQ = rotate(vector, q) val matrix = q.toRotationMatrix() @@ -36,7 +36,7 @@ class RotationTest { @Test fun fromRotation() { - val q = Quaternion.fromRotation(0.3.radians, Vector3D(1.0, 1.0, 1.0)) + val q = Quaternion.fromRotation(0.3.radians, Euclidean3DSpace.vector(1.0, 1.0, 1.0)) assertBufferEquals(DoubleBuffer(0.9887711, 0.0862781, 0.0862781, 0.0862781), q) } diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Vector2DTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Vector2DTest.kt index 5e45b4870..c98bfa45a 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 @@ -10,7 +10,7 @@ import kotlin.test.Test import kotlin.test.assertEquals internal class Vector2DTest { - private val vector = Vector2D(1.0, -7.999) + private val vector = Euclidean2DSpace.vector(1.0, -7.999) @Test fun size() { diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Vector3DTest.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/Vector3DTest.kt index 55bab4775..fabcaa9aa 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 @@ -10,7 +10,7 @@ import kotlin.test.Test import kotlin.test.assertEquals internal class Vector3DTest { - private val vector = Vector3D(1.0, -7.999, 0.001) + private val vector = Euclidean3DSpace.vector(1.0, -7.999, 0.001) @Test fun size() { diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/testUtils.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/testUtils.kt index 0f957529d..f8b64bc64 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 @@ -25,12 +25,12 @@ fun grid( return xs.flatMap { x -> ys.map { y -> x to y } } } -fun assertVectorEquals(expected: Vector2D, actual: Vector2D, absoluteTolerance: Double = 1e-6) { +fun assertVectorEquals(expected: DoubleVector2D, actual: DoubleVector2D, absoluteTolerance: Double = 1e-6) { assertEquals(expected.x, actual.x, absoluteTolerance) assertEquals(expected.y, actual.y, absoluteTolerance) } -fun assertVectorEquals(expected: Vector3D, actual: Vector3D, absoluteTolerance: Double = 1e-6) { +fun assertVectorEquals(expected: DoubleVector3D, actual: DoubleVector3D, absoluteTolerance: Double = 1e-6) { assertEquals(expected.x, actual.x, absoluteTolerance) assertEquals(expected.y, actual.y, absoluteTolerance) assertEquals(expected.z, actual.z, absoluteTolerance) diff --git a/kmath-geometry/src/jvmMain/kotlin/space/kscience/kmath/geometry/lineExtensions.kt b/kmath-geometry/src/jvmMain/kotlin/space/kscience/kmath/geometry/lineExtensions.kt new file mode 100644 index 000000000..5fcd2b23e --- /dev/null +++ b/kmath-geometry/src/jvmMain/kotlin/space/kscience/kmath/geometry/lineExtensions.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +import space.kscience.kmath.geometry.GeometrySpace +import space.kscience.kmath.geometry.Line +import space.kscience.kmath.geometry.LineSegment +import space.kscience.kmath.geometry.Vector +import space.kscience.kmath.operations.Group + +/** + * Get a line, containing this [LineSegment] + */ +context(Group) public val LineSegment.line: Line get() = Line(begin, end - begin) + +/** + * Get a length of a line segment + */ +context(GeometrySpace) public val LineSegment.length: Double get() = norm(end - begin) \ No newline at end of file diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/DubinsPath.kt index 134342b33..a7a98288c 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 @@ -6,8 +6,8 @@ package space.kscience.kmath.trajectory import space.kscience.kmath.geometry.Circle2D +import space.kscience.kmath.geometry.Euclidean2DSpace import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo -import space.kscience.kmath.geometry.Vector2D import kotlin.math.PI import kotlin.math.acos import kotlin.math.cos @@ -17,10 +17,10 @@ internal fun Pose2D.getLeftCircle(radius: Double): Circle2D = getTangentCircles( internal fun Pose2D.getRightCircle(radius: Double): Circle2D = getTangentCircles(radius).second -internal fun Pose2D.getTangentCircles(radius: Double): Pair { +internal fun Pose2D.getTangentCircles(radius: Double): Pair = with(Euclidean2DSpace) { val dX = radius * cos(theta) val dY = radius * sin(theta) - return Circle2D(Vector2D(x - dX, y + dY), radius) to Circle2D(Vector2D(x + dX, y - dY), radius) + 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) @@ -29,21 +29,21 @@ internal fun rightOuterTangent(a: Circle2D, b: Circle2D): StraightSegment = oute ArcSegment.Direction.RIGHT ) -private fun outerTangent(a: Circle2D, b: Circle2D, side: ArcSegment.Direction): StraightSegment { +private fun outerTangent(a: Circle2D, b: Circle2D, side: ArcSegment.Direction): StraightSegment = with(Euclidean2DSpace){ val centers = StraightSegment(a.center, b.center) val p1 = when (side) { - ArcSegment.Direction.LEFT -> Vector2D( + ArcSegment.Direction.LEFT -> vector( a.center.x - a.radius * cos(centers.theta), a.center.y + a.radius * sin(centers.theta) ) - ArcSegment.Direction.RIGHT -> Vector2D( + ArcSegment.Direction.RIGHT -> vector( a.center.x + a.radius * cos(centers.theta), a.center.y - a.radius * sin(centers.theta) ) } return StraightSegment( p1, - Vector2D(p1.x + (centers.end.x - centers.start.x), p1.y + (centers.end.y - centers.start.y)) + vector(p1.x + (centers.end.x - centers.start.x), p1.y + (centers.end.y - centers.start.y)) ) } @@ -53,7 +53,7 @@ internal fun leftInnerTangent(base: Circle2D, direction: Circle2D): StraightSegm internal fun rightInnerTangent(base: Circle2D, direction: Circle2D): StraightSegment? = innerTangent(base, direction, ArcSegment.Direction.RIGHT) -private fun innerTangent(base: Circle2D, direction: Circle2D, side: ArcSegment.Direction): StraightSegment? { +private fun innerTangent(base: Circle2D, direction: Circle2D, side: ArcSegment.Direction): StraightSegment? = with(Euclidean2DSpace){ val centers = StraightSegment(base.center, direction.center) if (centers.length < base.radius * 2) return null val angle = theta( @@ -64,8 +64,8 @@ private fun innerTangent(base: Circle2D, direction: Circle2D, side: ArcSegment.D ) val dX = base.radius * sin(angle) val dY = base.radius * cos(angle) - val p1 = Vector2D(base.center.x + dX, base.center.y + dY) - val p2 = Vector2D(direction.center.x - dX, direction.center.y - dY) + 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) } @@ -106,7 +106,7 @@ 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? { + 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) @@ -115,20 +115,20 @@ public class DubinsPath( var theta = theta(centers.theta - acos(centers.length / (turningRadius * 4))) var dX = turningRadius * sin(theta) var dY = turningRadius * cos(theta) - val p = Vector2D(c1.center.x + dX * 2, c1.center.y + dY * 2) + val p = vector(c1.center.x + dX * 2, c1.center.y + dY * 2) val e = Circle2D(p, turningRadius) - val p1 = Vector2D(c1.center.x + dX, c1.center.y + dY) + 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 = Vector2D(e.center.x + dX, e.center.y + dY) + val p2 = vector(e.center.x + dX, e.center.y + dY) val a1 = ArcSegment.of(c1.center, start, p1, ArcSegment.Direction.RIGHT) val a2 = ArcSegment.of(e.center, p1, p2, ArcSegment.Direction.LEFT) val a3 = ArcSegment.of(c2.center, p2, end, ArcSegment.Direction.RIGHT) return DubinsPath(a1, a2, a3) } - public fun lrl(start: Pose2D, end: Pose2D, turningRadius: Double): DubinsPath? { + 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) @@ -137,13 +137,13 @@ public class DubinsPath( var theta = theta(centers.theta + acos(centers.length / (turningRadius * 4))) var dX = turningRadius * sin(theta) var dY = turningRadius * cos(theta) - val p = Vector2D(c1.center.x + dX * 2, c1.center.y + dY * 2) + val p = vector(c1.center.x + dX * 2, c1.center.y + dY * 2) val e = Circle2D(p, turningRadius) - val p1 = Vector2D(c1.center.x + dX, c1.center.y + dY) + 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 = Vector2D(e.center.x + dX, e.center.y + dY) + 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) 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 index 1f7c4a52e..a7570156c 100644 --- a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Pose2D.kt +++ b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Pose2D.kt @@ -5,29 +5,29 @@ package space.kscience.kmath.trajectory +import space.kscience.kmath.geometry.DoubleVector2D import space.kscience.kmath.geometry.Vector -import space.kscience.kmath.geometry.Vector2D import kotlin.math.atan2 /** * Combination of [Vector] and its view angle */ -public interface Pose2D: Vector2D{ - public val coordinate: Vector2D +public interface Pose2D: DoubleVector2D{ + public val coordinate: DoubleVector2D public val theta: Double } public class PhaseVector2D( - override val coordinate: Vector2D, - public val velocity: Vector2D -): Pose2D, Vector2D by coordinate{ + 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: Vector2D, + override val coordinate: DoubleVector2D, override val theta: Double -) : Pose2D, Vector2D by coordinate +) : Pose2D, DoubleVector2D by coordinate -public fun Pose2D(coordinate: Vector2D, theta: Double): Pose2D = Pose2DImpl(coordinate, theta) \ No newline at end of file +public fun Pose2D(coordinate: DoubleVector2D, theta: Double): Pose2D = Pose2DImpl(coordinate, theta) \ No newline at end of file diff --git a/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory.kt b/kmath-trajectory/src/commonMain/kotlin/space/kscience/kmath/trajectory/Trajectory.kt index 2e97d43b0..554607cbd 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 @@ -6,8 +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.distanceTo -import space.kscience.kmath.geometry.Vector2D import space.kscience.kmath.geometry.circumference import kotlin.math.PI import kotlin.math.atan2 @@ -20,8 +20,8 @@ public sealed interface Trajectory { * Straight path segment. The order of start and end defines the direction */ public data class StraightSegment( - internal val start: Vector2D, - internal val end: Vector2D, + internal val start: DoubleVector2D, + internal val end: DoubleVector2D, ) : Trajectory { override val length: Double get() = start.distanceTo(end) @@ -68,9 +68,9 @@ public data class ArcSegment( } public companion object { - public fun of(center: Vector2D, start: Vector2D, end: Vector2D, direction: Direction): ArcSegment { + public fun of(center: DoubleVector2D, start: DoubleVector2D, end: DoubleVector2D, direction: Direction): ArcSegment { fun calculatePose( - vector: Vector2D, + vector: DoubleVector2D, theta: Double, direction: Direction, ): Pose2D = Pose2D( 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 7ee68bd92..5a9cc5be8 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 @@ -1,6 +1,6 @@ package space.kscience.kmath.trajectory -import space.kscience.kmath.geometry.Vector2D +import space.kscience.kmath.geometry.Euclidean2DSpace import kotlin.math.PI import kotlin.math.abs import kotlin.math.sin @@ -13,12 +13,12 @@ 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 { +fun StraightSegment.shift(shift: Int, width: Double): StraightSegment = with(Euclidean2DSpace){ val dX = width * sin(inverse().theta) val dY = width * sin(theta) return StraightSegment( - Vector2D(start.x - dX * shift, start.y - dY * shift), - Vector2D(end.x - dX * shift, end.y - dY * shift) + 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 09375a400..68a5f8454 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 @@ -5,8 +5,7 @@ package space.kscience.kmath.trajectory.dubins -import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo -import space.kscience.kmath.geometry.Vector2D +import space.kscience.kmath.geometry.Euclidean2DSpace import space.kscience.kmath.trajectory.* import kotlin.test.Test import kotlin.test.assertNotNull @@ -16,8 +15,8 @@ import kotlin.test.assertTrue class DubinsTests { @Test - fun dubinsTest() { - val straight = StraightSegment(Vector2D(0.0, 0.0), Vector2D(100.0, 100.0)) + fun dubinsTest() = with(Euclidean2DSpace){ + val straight = StraightSegment(vector(0.0, 0.0), vector(100.0, 100.0)) val lineP1 = straight.shift(1, 10.0).inverse() val start = Pose2D(straight.end, straight.theta) 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 c66fa201b..88423ee99 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 @@ -1,7 +1,7 @@ package space.kscience.kmath.trajectory.segments import space.kscience.kmath.geometry.Circle2D -import space.kscience.kmath.geometry.Vector2D +import space.kscience.kmath.geometry.Euclidean2DSpace import space.kscience.kmath.geometry.circumference import space.kscience.kmath.trajectory.ArcSegment import space.kscience.kmath.trajectory.radiansToDegrees @@ -11,9 +11,9 @@ import kotlin.test.assertEquals class ArcTests { @Test - fun arcTest() { - val circle = Circle2D(Vector2D(0.0, 0.0), 2.0) - val arc = ArcSegment.of(circle.center, Vector2D(-2.0, 0.0), Vector2D(0.0, 2.0), ArcSegment.Direction.RIGHT) + fun arcTest() = with(Euclidean2DSpace){ + val circle = Circle2D(vector(0.0, 0.0), 2.0) + val arc = ArcSegment.of(circle.center, vector(-2.0, 0.0), vector(0.0, 2.0), ArcSegment.Direction.RIGHT) assertEquals(circle.circumference / 4, arc.length, 1.0) assertEquals(0.0, arc.start.theta.radiansToDegrees()) assertEquals(90.0, arc.end.theta.radiansToDegrees()) diff --git a/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/CircleTests.kt b/kmath-trajectory/src/commonTest/kotlin/space/kscience/kmath/trajectory/segments/CircleTests.kt index 5170c1db5..f1f9c6a3b 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 @@ -6,7 +6,7 @@ package space.kscience.kmath.trajectory.segments import space.kscience.kmath.geometry.Circle2D -import space.kscience.kmath.geometry.Vector2D +import space.kscience.kmath.geometry.Euclidean2DSpace import space.kscience.kmath.geometry.circumference import space.kscience.kmath.trajectory.maxFloatDelta import kotlin.test.Test @@ -16,7 +16,7 @@ class CircleTests { @Test fun arcTest() { - val center = Vector2D(0.0, 0.0) + val center = Euclidean2DSpace.vector(0.0, 0.0) val radius = 2.0 val expectedCircumference = 12.56637 val circle = Circle2D(center, radius) 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 11eaa0fb3..b8fe256c7 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 @@ -1,7 +1,6 @@ package space.kscience.kmath.trajectory.segments import space.kscience.kmath.geometry.Euclidean2DSpace -import space.kscience.kmath.geometry.Vector2D import space.kscience.kmath.trajectory.StraightSegment import space.kscience.kmath.trajectory.radiansToDegrees import kotlin.math.pow @@ -12,22 +11,22 @@ import kotlin.test.assertEquals class LineTests { @Test - fun lineTest() { - val straight = StraightSegment(Vector2D(0.0, 0.0), Vector2D(100.0, 100.0)) + fun lineTest() = with(Euclidean2DSpace){ + val straight = StraightSegment(vector(0.0, 0.0), vector(100.0, 100.0)) assertEquals(sqrt(100.0.pow(2) + 100.0.pow(2)), straight.length) assertEquals(45.0, straight.theta.radiansToDegrees()) } @Test - fun lineAngleTest() { + fun lineAngleTest() = with(Euclidean2DSpace){ //val zero = Vector2D(0.0, 0.0) - val north = StraightSegment(Euclidean2DSpace.zero, Vector2D(0.0, 2.0)) + val north = StraightSegment(Euclidean2DSpace.zero, vector(0.0, 2.0)) assertEquals(0.0, north.theta.radiansToDegrees()) - val east = StraightSegment(Euclidean2DSpace.zero, Vector2D(2.0, 0.0)) + val east = StraightSegment(Euclidean2DSpace.zero, vector(2.0, 0.0)) assertEquals(90.0, east.theta.radiansToDegrees()) - val south = StraightSegment(Euclidean2DSpace.zero, Vector2D(0.0, -2.0)) + val south = StraightSegment(Euclidean2DSpace.zero, vector(0.0, -2.0)) assertEquals(180.0, south.theta.radiansToDegrees()) - val west = StraightSegment(Euclidean2DSpace.zero, Vector2D(-2.0, 0.0)) + val west = StraightSegment(Euclidean2DSpace.zero, vector(-2.0, 0.0)) assertEquals(270.0, west.theta.radiansToDegrees()) } } -- 2.34.1 From ad9775132792b93e33c143cbfe38b347bc26abf3 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 4 Sep 2022 20:59:30 +0300 Subject: [PATCH 176/275] Refactor for build tools 0.13.0 --- build.gradle.kts | 11 ++++++++-- .../kmath/structures/StreamDoubleFieldND.kt | 4 ++++ .../kscience/kmath/tensors/OLSWithSVD.kt | 2 ++ .../kscience/kmath/tensors/neuralNetwork.kt | 3 +++ gradle.properties | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- kmath-ast/build.gradle.kts | 7 +++++-- .../ast/rendering/multiplatformToString.kt | 9 ++++++++ .../kscience/kmath/ast/runCompilerTest.kt | 10 +++++++++ kmath-commons/build.gradle.kts | 3 +-- kmath-complex/build.gradle.kts | 12 ++++++----- kmath-core/build.gradle.kts | 21 +++++++------------ kmath-coroutines/build.gradle.kts | 8 ++++--- kmath-dimensions/build.gradle.kts | 5 ++++- kmath-ejml/build.gradle.kts | 3 +-- .../space/kscience/kmath/ejml/_generated.kt | 4 ++-- kmath-for-real/build.gradle.kts | 8 ++++--- kmath-functions/build.gradle.kts | 8 ++++--- kmath-geometry/build.gradle.kts | 5 ++++- kmath-histograms/build.gradle.kts | 5 ++++- kmath-kotlingrad/build.gradle.kts | 3 +-- kmath-memory/build.gradle.kts | 5 ++++- .../kscience/kmath/multik/MultikNDTest.kt | 2 ++ kmath-nd4j/build.gradle.kts | 3 +-- .../kscience/kmath/nd4j/Nd4jArrayAlgebra.kt | 2 ++ .../kscience/kmath/nd4j/Nd4jTensorAlgebra.kt | 3 +++ kmath-optimization/build.gradle.kts | 5 ++++- kmath-polynomial/build.gradle.kts | 6 ++++-- kmath-stat/build.gradle.kts | 5 ++++- kmath-symja/build.gradle.kts | 3 +-- .../tensorflow/DoubleTensorFlowAlgebra.kt | 1 + .../kmath/tensorflow/DoubleTensorFlowOps.kt | 2 ++ kmath-tensors/build.gradle.kts | 8 ++++--- kmath-trajectory/build.gradle.kts | 8 ++++--- kmath-viktor/build.gradle.kts | 5 ++--- .../kscience/kmath/viktor/ViktorBuffer.kt | 2 +- test-utils/build.gradle.kts | 5 ++++- 37 files changed, 136 insertions(+), 64 deletions(-) create mode 100644 kmath-ast/src/nativeMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt create mode 100644 kmath-ast/src/nativeTest/kotlin/space/kscience/kmath/ast/runCompilerTest.kt diff --git a/build.gradle.kts b/build.gradle.kts index 04cb76285..4a083b437 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,6 @@ +import space.kscience.gradle.useApache2Licence +import space.kscience.gradle.useSPCTeam + plugins { id("space.kscience.gradle.project") id("org.jetbrains.kotlinx.kover") version "0.5.0" @@ -68,8 +71,12 @@ subprojects { readme.readmeTemplate = file("docs/templates/README-TEMPLATE.md") ksciencePublish { - github("kmath", addToRelease = false) - space() + pom("https://github.com/SciProgCentre/kmath") { + useApache2Licence() + useSPCTeam() + } + github("kmath", "SciProgCentre", addToRelease = false) + space("https://maven.pkg.jetbrains.space/mipt-npm/p/sci/dev") 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 aed0a7868..4aa420305 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.structures +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.* import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.ExtendedField @@ -49,6 +50,7 @@ class StreamDoubleFieldND(override val shape: IntArray) : FieldND.map( transform: DoubleField.(Double) -> Double, ): BufferND { @@ -56,6 +58,7 @@ class StreamDoubleFieldND(override val shape: IntArray) : FieldND.mapIndexed( transform: DoubleField.(index: IntArray, Double) -> Double, ): BufferND { @@ -69,6 +72,7 @@ class StreamDoubleFieldND(override val shape: IntArray) : FieldND, right: StructureND, diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt index f7c5bb4b7..8082ed8e2 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.tensors +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.DoubleTensorAlgebra @@ -13,6 +14,7 @@ import kotlin.math.abs // OLS estimator using SVD +@OptIn(PerformancePitfall::class) fun main() { //seed for random val randSeed = 100500L 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 cbc83c336..502f6d53f 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.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(PerformancePitfall::class) + package space.kscience.kmath.tensors +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra import space.kscience.kmath.tensors.core.DoubleTensor diff --git a/gradle.properties b/gradle.properties index b3e3f4cda..0d1506980 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,4 +12,4 @@ org.gradle.configureondemand=true org.gradle.parallel=true org.gradle.jvmargs=-Xmx4096m -toolsVersion=0.12.0-kotlin-1.7.20-Beta +toolsVersion=0.13.0-kotlin-1.7.20-Beta diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index aa991fcea..8049c684f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index c1333eba5..7fd0f43f7 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -1,6 +1,9 @@ plugins { - kotlin("multiplatform") - id("space.kscience.gradle.common") + id("space.kscience.gradle.mpp") +} + +kscience{ + native() } kotlin.js { diff --git a/kmath-ast/src/nativeMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt b/kmath-ast/src/nativeMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt new file mode 100644 index 000000000..ec66be830 --- /dev/null +++ b/kmath-ast/src/nativeMain/kotlin/space/kscience/kmath/ast/rendering/multiplatformToString.kt @@ -0,0 +1,9 @@ +/* + * Copyright 2018-2022 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.ast.rendering + +internal actual fun Double.multiplatformToString(): String = toString() +internal actual fun Float.multiplatformToString(): String = toString() diff --git a/kmath-ast/src/nativeTest/kotlin/space/kscience/kmath/ast/runCompilerTest.kt b/kmath-ast/src/nativeTest/kotlin/space/kscience/kmath/ast/runCompilerTest.kt new file mode 100644 index 000000000..0674b0492 --- /dev/null +++ b/kmath-ast/src/nativeTest/kotlin/space/kscience/kmath/ast/runCompilerTest.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2018-2022 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.ast + +internal actual inline fun runCompilerTest(action: CompilerTestContext.() -> Unit) { + //doNothing +} \ No newline at end of file diff --git a/kmath-commons/build.gradle.kts b/kmath-commons/build.gradle.kts index 643307b48..50fef7ac8 100644 --- a/kmath-commons/build.gradle.kts +++ b/kmath-commons/build.gradle.kts @@ -1,6 +1,5 @@ plugins { - kotlin("jvm") - id("space.kscience.gradle.common") + id("space.kscience.gradle.jvm") } description = "Commons math binding for kmath" diff --git a/kmath-complex/build.gradle.kts b/kmath-complex/build.gradle.kts index dbe96b153..b63def0a7 100644 --- a/kmath-complex/build.gradle.kts +++ b/kmath-complex/build.gradle.kts @@ -1,7 +1,9 @@ plugins { - kotlin("multiplatform") - id("space.kscience.gradle.common") - id("space.kscience.gradle.native") + id("space.kscience.gradle.mpp") +} + +kscience { + native() } kotlin.sourceSets { @@ -20,14 +22,14 @@ readme { feature( id = "complex", ref = "src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt" - ){ + ) { "Complex numbers operations" } feature( id = "quaternion", ref = "src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt" - ){ + ) { "Quaternions and their composition" } } diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index d055b5350..f33d33324 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -1,6 +1,13 @@ plugins { id("space.kscience.gradle.mpp") - id("space.kscience.gradle.native") +} + +kscience{ + native() + + dependencies { + api(project(":kmath-memory")) + } } kotlin.sourceSets { @@ -10,20 +17,8 @@ kotlin.sourceSets { it.optIn("space.kscience.kmath.misc.PerformancePitfall") it.optIn("space.kscience.kmath.misc.UnstableKMathAPI") } - - commonMain { - dependencies { - api(project(":kmath-memory")) - } - } } -//generateUml { -// classTree { -// -// } -//} - readme { description = "Core classes, algebra definitions, basic linear algebra" maturity = space.kscience.gradle.Maturity.DEVELOPMENT diff --git a/kmath-coroutines/build.gradle.kts b/kmath-coroutines/build.gradle.kts index 104adf268..529084619 100644 --- a/kmath-coroutines/build.gradle.kts +++ b/kmath-coroutines/build.gradle.kts @@ -1,7 +1,9 @@ plugins { - kotlin("multiplatform") - id("space.kscience.gradle.common") - id("space.kscience.gradle.native") + id("space.kscience.gradle.mpp") +} + +kscience{ + native() } kotlin.sourceSets { diff --git a/kmath-dimensions/build.gradle.kts b/kmath-dimensions/build.gradle.kts index 1c042ab70..29c0eccb6 100644 --- a/kmath-dimensions/build.gradle.kts +++ b/kmath-dimensions/build.gradle.kts @@ -1,6 +1,9 @@ plugins { id("space.kscience.gradle.mpp") - id("space.kscience.gradle.native") +} + +kscience{ + native() } description = "A proof of concept module for adding type-safe dimensions to structures" diff --git a/kmath-ejml/build.gradle.kts b/kmath-ejml/build.gradle.kts index d400d6600..d7f780d79 100644 --- a/kmath-ejml/build.gradle.kts +++ b/kmath-ejml/build.gradle.kts @@ -1,8 +1,7 @@ import space.kscience.kmath.ejml.codegen.ejmlCodegen plugins { - kotlin("jvm") - id("space.kscience.gradle.common") + id("space.kscience.gradle.jvm") } dependencies { diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt index 5426055b3..aac327a84 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt @@ -1,6 +1,6 @@ /* - * Copyright 2018-2022 KMath contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + * Copyright 2018-2021 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. */ /* This file is generated with buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt */ diff --git a/kmath-for-real/build.gradle.kts b/kmath-for-real/build.gradle.kts index 6b6242c24..308b8d732 100644 --- a/kmath-for-real/build.gradle.kts +++ b/kmath-for-real/build.gradle.kts @@ -1,7 +1,9 @@ plugins { - kotlin("multiplatform") - id("space.kscience.gradle.common") - id("space.kscience.gradle.native") + id("space.kscience.gradle.mpp") +} + +kscience{ + native() } kotlin.sourceSets.commonMain { diff --git a/kmath-functions/build.gradle.kts b/kmath-functions/build.gradle.kts index c68102c2e..2e7b023c1 100644 --- a/kmath-functions/build.gradle.kts +++ b/kmath-functions/build.gradle.kts @@ -1,7 +1,9 @@ plugins { - kotlin("multiplatform") - id("space.kscience.gradle.common") - id("space.kscience.gradle.native") + id("space.kscience.gradle.mpp") +} + +kscience{ + native() } description = "Functions, integration and interpolation" diff --git a/kmath-geometry/build.gradle.kts b/kmath-geometry/build.gradle.kts index c2057bcbe..b868af8d0 100644 --- a/kmath-geometry/build.gradle.kts +++ b/kmath-geometry/build.gradle.kts @@ -1,6 +1,9 @@ plugins { id("space.kscience.gradle.mpp") - id("space.kscience.gradle.native") +} + +kscience{ + native() } kotlin.sourceSets.commonMain { diff --git a/kmath-histograms/build.gradle.kts b/kmath-histograms/build.gradle.kts index 94d1f5fb7..d31526a74 100644 --- a/kmath-histograms/build.gradle.kts +++ b/kmath-histograms/build.gradle.kts @@ -1,6 +1,9 @@ plugins { id("space.kscience.gradle.mpp") - id("space.kscience.gradle.native") +} + +kscience{ + native() } //apply(plugin = "kotlinx-atomicfu") diff --git a/kmath-kotlingrad/build.gradle.kts b/kmath-kotlingrad/build.gradle.kts index a7f4ee37f..cf4a4bc1d 100644 --- a/kmath-kotlingrad/build.gradle.kts +++ b/kmath-kotlingrad/build.gradle.kts @@ -1,6 +1,5 @@ plugins { - kotlin("jvm") - id("space.kscience.gradle.common") + id("space.kscience.gradle.jvm") } kotlin.sourceSets diff --git a/kmath-memory/build.gradle.kts b/kmath-memory/build.gradle.kts index 55a7ff6aa..50eb448a7 100644 --- a/kmath-memory/build.gradle.kts +++ b/kmath-memory/build.gradle.kts @@ -1,6 +1,9 @@ plugins { id("space.kscience.gradle.mpp") - id("space.kscience.gradle.native") +} + +kscience { + native() } readme { 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 8ad220221..392532d8e 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 @@ -6,6 +6,7 @@ package space.kscience.kmath.multik import org.jetbrains.kotlinx.multik.default.DefaultEngine +import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.one import space.kscience.kmath.operations.DoubleField @@ -14,6 +15,7 @@ import space.kscience.kmath.tensors.core.tensorAlgebra import kotlin.test.Test import kotlin.test.assertTrue +@OptIn(PerformancePitfall::class) internal class MultikNDTest { val multikAlgebra = MultikDoubleAlgebra(DefaultEngine()) diff --git a/kmath-nd4j/build.gradle.kts b/kmath-nd4j/build.gradle.kts index 11af7d6dc..e5c4af891 100644 --- a/kmath-nd4j/build.gradle.kts +++ b/kmath-nd4j/build.gradle.kts @@ -1,6 +1,5 @@ plugins { - kotlin("jvm") - id("space.kscience.gradle.common") + id("space.kscience.gradle.jvm") } description = "ND4J NDStructure implementation and according NDAlgebra classes" 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 f359b9115..859773211 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt @@ -45,6 +45,7 @@ public sealed interface Nd4jArrayAlgebra> : AlgebraND.mapIndexed( transform: C.(index: IntArray, T) -> T, ): Nd4jArrayStructure { @@ -53,6 +54,7 @@ public sealed interface Nd4jArrayAlgebra> : AlgebraND, right: StructureND, diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt index 5ecfe30d6..b6a2029e7 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 @@ -40,12 +40,15 @@ public sealed interface Nd4jTensorAlgebra> : AnalyticTe override fun structureND(shape: Shape, initializer: A.(IntArray) -> T): Nd4jArrayStructure + @OptIn(PerformancePitfall::class) override fun StructureND.map(transform: A.(T) -> T): Nd4jArrayStructure = structureND(shape) { index -> elementAlgebra.transform(get(index)) } + @OptIn(PerformancePitfall::class) override fun StructureND.mapIndexed(transform: A.(index: IntArray, T) -> T): Nd4jArrayStructure = structureND(shape) { index -> elementAlgebra.transform(index, get(index)) } + @OptIn(PerformancePitfall::class) override fun zip(left: StructureND, right: StructureND, transform: A.(T, T) -> T): Nd4jArrayStructure { require(left.shape.contentEquals(right.shape)) return structureND(left.shape) { index -> elementAlgebra.transform(left[index], right[index]) } diff --git a/kmath-optimization/build.gradle.kts b/kmath-optimization/build.gradle.kts index 53f379830..f4256b9aa 100644 --- a/kmath-optimization/build.gradle.kts +++ b/kmath-optimization/build.gradle.kts @@ -1,6 +1,9 @@ plugins { id("space.kscience.gradle.mpp") - id("space.kscience.gradle.native") +} + +kscience{ + native() } kotlin.sourceSets { diff --git a/kmath-polynomial/build.gradle.kts b/kmath-polynomial/build.gradle.kts index c6946878c..4e469f0d1 100644 --- a/kmath-polynomial/build.gradle.kts +++ b/kmath-polynomial/build.gradle.kts @@ -1,7 +1,9 @@ plugins { id("space.kscience.gradle.mpp") - // Disable native target to avoid CI crashes -// id("space.kscience.gradle.native") +} + +kscience{ + native() } description = "Polynomials, rational functions, and utilities" diff --git a/kmath-stat/build.gradle.kts b/kmath-stat/build.gradle.kts index 1d1831047..f6ca54e17 100644 --- a/kmath-stat/build.gradle.kts +++ b/kmath-stat/build.gradle.kts @@ -1,6 +1,9 @@ plugins { id("space.kscience.gradle.mpp") - id("space.kscience.gradle.native") +} + +kscience{ + native() } kotlin.sourceSets { diff --git a/kmath-symja/build.gradle.kts b/kmath-symja/build.gradle.kts index 1984236ca..8741de2ae 100644 --- a/kmath-symja/build.gradle.kts +++ b/kmath-symja/build.gradle.kts @@ -4,8 +4,7 @@ */ plugins { - kotlin("jvm") - id("space.kscience.gradle.common") + id("space.kscience.gradle.jvm") } description = "Symja integration module" 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 fa7050d2a..c4d192792 100644 --- a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowAlgebra.kt +++ b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowAlgebra.kt @@ -93,6 +93,7 @@ public fun DoubleField.produceWithTF( * * The resulting tensors are available outside of scope */ +@OptIn(UnstableKMathAPI::class) public fun DoubleField.produceMapWithTF( block: DoubleTensorFlowAlgebra.() -> Map>, ): Map> = Graph().use { graph -> diff --git a/kmath-tensorflow/src/test/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowOps.kt b/kmath-tensorflow/src/test/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowOps.kt index 21340a8db..a35556be1 100644 --- a/kmath-tensorflow/src/test/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowOps.kt +++ b/kmath-tensorflow/src/test/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowOps.kt @@ -6,6 +6,7 @@ package space.kscience.kmath.tensorflow import org.junit.jupiter.api.Test +import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.get import space.kscience.kmath.nd.structureND import space.kscience.kmath.operations.DoubleField @@ -13,6 +14,7 @@ import space.kscience.kmath.tensors.core.DoubleTensorAlgebra import space.kscience.kmath.tensors.core.DoubleTensorAlgebra.Companion.sum import kotlin.test.assertEquals +@OptIn(UnstableKMathAPI::class) class DoubleTensorFlowOps { @Test fun basicOps() { diff --git a/kmath-tensors/build.gradle.kts b/kmath-tensors/build.gradle.kts index b2a4c36bd..3d92f07b6 100644 --- a/kmath-tensors/build.gradle.kts +++ b/kmath-tensors/build.gradle.kts @@ -1,7 +1,9 @@ plugins { - kotlin("multiplatform") - id("space.kscience.gradle.common") - id("space.kscience.gradle.native") + id("space.kscience.gradle.mpp") +} + +kscience{ + native() } kotlin.sourceSets { diff --git a/kmath-trajectory/build.gradle.kts b/kmath-trajectory/build.gradle.kts index f4dba25ab..5ee0a241d 100644 --- a/kmath-trajectory/build.gradle.kts +++ b/kmath-trajectory/build.gradle.kts @@ -1,7 +1,9 @@ plugins { - kotlin("multiplatform") - id("space.kscience.gradle.common") - id("space.kscience.gradle.native") + id("space.kscience.gradle.mpp") +} + +kscience{ + native() } kotlin.sourceSets.commonMain { diff --git a/kmath-viktor/build.gradle.kts b/kmath-viktor/build.gradle.kts index 1b22e9c38..7a135f316 100644 --- a/kmath-viktor/build.gradle.kts +++ b/kmath-viktor/build.gradle.kts @@ -1,13 +1,12 @@ plugins { - kotlin("jvm") - id("space.kscience.gradle.common") + id("space.kscience.gradle.jvm") } description = "Binding for https://github.com/JetBrains-Research/viktor" dependencies { api(project(":kmath-core")) - api("org.jetbrains.bio:viktor:1.1.0") + api("org.jetbrains.bio:viktor:1.2.0") } readme { diff --git a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorBuffer.kt b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorBuffer.kt index 90d5ad9a9..52dc1e192 100644 --- a/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorBuffer.kt +++ b/kmath-viktor/src/main/kotlin/space/kscience/kmath/viktor/ViktorBuffer.kt @@ -13,7 +13,7 @@ import space.kscience.kmath.structures.MutableBuffer @JvmInline public value class ViktorBuffer(public val flatArray: F64FlatArray) : MutableBuffer { override val size: Int - get() = flatArray.size + get() = flatArray.length override inline fun get(index: Int): Double = flatArray[index] diff --git a/test-utils/build.gradle.kts b/test-utils/build.gradle.kts index 49c4758e3..98bd7328d 100644 --- a/test-utils/build.gradle.kts +++ b/test-utils/build.gradle.kts @@ -1,6 +1,9 @@ plugins { id("space.kscience.gradle.mpp") - id("space.kscience.gradle.native") +} + +kscience{ + native() } kotlin.sourceSets { -- 2.34.1 From 5042fda751940c04d944046d645a58c685776a75 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 5 Sep 2022 16:30:39 +0300 Subject: [PATCH 177/275] Int Tensor Algebra implementation --- build.gradle.kts | 2 +- buildSrc/build.gradle.kts | 3 +- .../space/kscience/kmath/nd/BufferND.kt | 2 +- .../space/kscience/kmath/nd/DoubleFieldND.kt | 2 +- .../space/kscience/kmath/nd/IntRingND.kt | 50 ++ .../space/kscience/kmath/nd/ShortRingND.kt | 5 +- .../space/kscience/kmath/nd/StructureND.kt | 17 +- .../kmath/operations/BufferAlgebra.kt | 3 + kmath-geometry/build.gradle.kts | 10 +- kmath-tensors/build.gradle.kts | 4 + .../kmath/tensors/core/DoubleTensorAlgebra.kt | 6 +- .../kscience/kmath/tensors/core/IntTensor.kt | 10 +- .../kmath/tensors/core/IntTensorAlgebra.kt | 493 ++++++++++++++++++ .../kmath/tensors/core/internal/checks.kt | 9 +- .../tensors/core/internal/tensorCastsUtils.kt | 4 +- .../tensors/core/tensorAlgebraExtensions.kt | 5 +- kmath-trajectory/build.gradle.kts | 4 +- 17 files changed, 593 insertions(+), 36 deletions(-) create mode 100644 kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/IntRingND.kt create mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensorAlgebra.kt diff --git a/build.gradle.kts b/build.gradle.kts index 4a083b437..890824d65 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,7 +14,7 @@ allprojects { } group = "space.kscience" - version = "0.3.1-dev-2" + version = "0.3.1-dev-3" } subprojects { diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 9bf5d03d0..0f95a7b3f 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -1,8 +1,7 @@ plugins { - kotlin("jvm") version "1.7.20-Beta" `kotlin-dsl` `version-catalog` - alias(npmlibs.plugins.kotlin.plugin.serialization) + kotlin("plugin.serialization") version "1.6.21" } java.targetCompatibility = JavaVersion.VERSION_11 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 5484ce545..1eb08fa8c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/BufferND.kt @@ -56,7 +56,7 @@ public inline fun StructureND.mapToBuffer( * @param strides The strides to access elements of [MutableBuffer] by linear indices. * @param buffer The underlying buffer. */ -public class MutableBufferND( +public open class MutableBufferND( strides: ShapeIndexer, override val buffer: MutableBuffer, ) : MutableStructureND, BufferND(strides, buffer) { 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 7f8d3c55d..4e8876731 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 @@ -16,7 +16,7 @@ import kotlin.math.pow as kpow public class DoubleBufferND( indexes: ShapeIndexer, override val buffer: DoubleBuffer, -) : BufferND(indexes, buffer) +) : MutableBufferND(indexes, buffer) public sealed class DoubleFieldOpsND : BufferedFieldOpsND(DoubleField.bufferAlgebra), diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/IntRingND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/IntRingND.kt new file mode 100644 index 000000000..ac01239a9 --- /dev/null +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/IntRingND.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2018-2022 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.nd + +import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.operations.IntRing +import space.kscience.kmath.operations.NumbersAddOps +import space.kscience.kmath.operations.bufferAlgebra +import space.kscience.kmath.structures.IntBuffer +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract + +public class IntBufferND( + indexes: ShapeIndexer, + override val buffer: IntBuffer, +) : MutableBufferND(indexes, buffer) + +public sealed class IntRingOpsND : BufferedRingOpsND(IntRing.bufferAlgebra) { + + override fun structureND(shape: Shape, initializer: IntRing.(IntArray) -> Int): IntBufferND { + val indexer = indexerBuilder(shape) + return IntBufferND( + indexer, + IntBuffer(indexer.linearSize) { offset -> + elementAlgebra.initializer(indexer.index(offset)) + } + ) + } + + public companion object : IntRingOpsND() +} + +@OptIn(UnstableKMathAPI::class) +public class IntRingND( + override val shape: Shape +) : IntRingOpsND(), RingND, NumbersAddOps> { + + override fun number(value: Number): BufferND { + val int = value.toInt() // minimize conversions + return structureND(shape) { int } + } +} + +public inline fun IntRing.withNdAlgebra(vararg shape: Int, action: IntRingND.() -> R): R { + contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } + return IntRingND(shape).run(action) +} diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt index ea37da7a3..249b6801d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShortRingND.kt @@ -22,8 +22,9 @@ public class ShortRingND( ) : ShortRingOpsND(), RingND, NumbersAddOps> { override fun number(value: Number): BufferND { - val d = value.toShort() // minimize conversions - return structureND(shape) { d } + val short + = value.toShort() // minimize conversions + return structureND(shape) { short } } } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt index 0fed49f40..aece10c2e 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 @@ -82,7 +82,7 @@ public interface StructureND : Featured, WithShape { public fun contentEquals( st1: StructureND, st2: StructureND, - tolerance: Double = 1e-11 + tolerance: Double = 1e-11, ): Boolean { if (st1 === st2) return true @@ -101,11 +101,17 @@ public interface StructureND : Featured, WithShape { val bufferRepr: String = when (structure.shape.size) { 1 -> (0 until structure.shape[0]).map { structure[it] } .joinToString(prefix = "[", postfix = "]", separator = ", ") - 2 -> (0 until structure.shape[0]).joinToString(prefix = "[\n", postfix = "\n]", separator = ",\n") { i -> + + 2 -> (0 until structure.shape[0]).joinToString( + prefix = "[\n", + postfix = "\n]", + separator = ",\n" + ) { i -> (0 until structure.shape[1]).joinToString(prefix = " [", postfix = "]", separator = ", ") { j -> structure[i, j].toString() } } + else -> "..." } val className = structure::class.simpleName ?: "StructureND" @@ -226,6 +232,13 @@ public interface MutableStructureND : StructureND { public operator fun set(index: IntArray, value: T) } +/** + * Set value at specified indices + */ +public operator fun MutableStructureND.set(vararg index: Int, value: T) { + set(index, value) +} + /** * Transform a structure element-by element in place. */ 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 3af77856c..af0bc4d9b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BufferAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BufferAlgebra.kt @@ -142,6 +142,9 @@ public open class BufferRingOps>( super.binaryOperationFunction(operation) } +public val IntRing.bufferAlgebra: BufferRingOps + get() = BufferRingOps(IntRing) + public val ShortRing.bufferAlgebra: BufferRingOps get() = BufferRingOps(ShortRing) diff --git a/kmath-geometry/build.gradle.kts b/kmath-geometry/build.gradle.kts index b868af8d0..52d76d5d2 100644 --- a/kmath-geometry/build.gradle.kts +++ b/kmath-geometry/build.gradle.kts @@ -4,18 +4,12 @@ plugins { kscience{ native() -} - -kotlin.sourceSets.commonMain { - dependencies { + withContextReceivers() + dependencies{ api(projects.kmath.kmathComplex) } } -kscience { - withContextReceivers() -} - readme { maturity = space.kscience.gradle.Maturity.PROTOTYPE } diff --git a/kmath-tensors/build.gradle.kts b/kmath-tensors/build.gradle.kts index 3d92f07b6..78ea4ba42 100644 --- a/kmath-tensors/build.gradle.kts +++ b/kmath-tensors/build.gradle.kts @@ -4,6 +4,10 @@ plugins { kscience{ native() + dependencies { + api(projects.kmathCore) + api(projects.kmathStat) + } } kotlin.sourceSets { 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 53115d5e5..94ad3f43c 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 @@ -31,8 +31,7 @@ public open class DoubleTensorAlgebra : public companion object : DoubleTensorAlgebra() - override val elementAlgebra: DoubleField - get() = DoubleField + override val elementAlgebra: DoubleField get() = DoubleField /** @@ -622,7 +621,8 @@ public open class DoubleTensorAlgebra : } val resNumElements = resShape.reduce(Int::times) val init = foldFunction(DoubleArray(1) { 0.0 }) - val resTensor = BufferedTensor(resShape, + val resTensor = BufferedTensor( + resShape, MutableBuffer.auto(resNumElements) { init }, 0 ) for (index in resTensor.indices) { 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 ccff9606e..a2b942bf0 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 @@ -11,11 +11,11 @@ import space.kscience.kmath.tensors.core.internal.array /** * Default [BufferedTensor] implementation for [Int] values */ -public class IntTensor internal constructor( +public class IntTensor @PublishedApi internal constructor( shape: IntArray, buffer: IntArray, - offset: Int = 0 -) : BufferedTensor(shape, IntBuffer(buffer), offset){ - public fun asDouble() : DoubleTensor = - DoubleTensor(shape, mutableBuffer.array().map{ it.toDouble()}.toDoubleArray(), bufferStart) + offset: Int = 0, +) : BufferedTensor(shape, IntBuffer(buffer), offset) { + public fun asDouble(): DoubleTensor = + DoubleTensor(shape, mutableBuffer.array().map { it.toDouble() }.toDoubleArray(), bufferStart) } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensorAlgebra.kt new file mode 100644 index 000000000..0c8ddcf87 --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensorAlgebra.kt @@ -0,0 +1,493 @@ +/* + * Copyright 2018-2022 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + + +@file:OptIn(PerformancePitfall::class) + +package space.kscience.kmath.tensors.core + +import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.nd.* +import space.kscience.kmath.operations.IntRing +import space.kscience.kmath.structures.MutableBuffer +import space.kscience.kmath.tensors.api.* +import space.kscience.kmath.tensors.core.internal.* +import kotlin.math.* + +/** + * Implementation of basic operations over double tensors and basic algebra operations on them. + */ +public open class IntTensorAlgebra : TensorAlgebra { + + public companion object : IntTensorAlgebra() + + override fun StructureND.dot(other: StructureND): Tensor { + TODO("Not yet implemented") + } + + override val elementAlgebra: IntRing get() = IntRing + + + /** + * Applies the [transform] function to each element of the tensor and returns the resulting modified tensor. + * + * @param transform the function to be applied to each element of the tensor. + * @return the resulting tensor after applying the function. + */ + @PerformancePitfall + @Suppress("OVERRIDE_BY_INLINE") + final override inline fun StructureND.map(transform: IntRing.(Int) -> Int): IntTensor { + val tensor = this.tensor + //TODO remove additional copy + val sourceArray = tensor.copyArray() + val array = IntArray(tensor.numElements) { IntRing.transform(sourceArray[it]) } + return IntTensor( + tensor.shape, + array, + tensor.bufferStart + ) + } + + @PerformancePitfall + @Suppress("OVERRIDE_BY_INLINE") + final override inline fun StructureND.mapIndexed(transform: IntRing.(index: IntArray, Int) -> Int): IntTensor { + val tensor = this.tensor + //TODO remove additional copy + val sourceArray = tensor.copyArray() + val array = IntArray(tensor.numElements) { IntRing.transform(tensor.indices.index(it), sourceArray[it]) } + return IntTensor( + tensor.shape, + array, + tensor.bufferStart + ) + } + + @PerformancePitfall + override fun zip( + left: StructureND, + right: StructureND, + transform: IntRing.(Int, Int) -> Int, + ): IntTensor { + require(left.shape.contentEquals(right.shape)) { + "The shapes in zip are not equal: left - ${left.shape}, right - ${right.shape}" + } + val leftTensor = left.tensor + val leftArray = leftTensor.copyArray() + val rightTensor = right.tensor + val rightArray = rightTensor.copyArray() + val array = IntArray(leftTensor.numElements) { IntRing.transform(leftArray[it], rightArray[it]) } + return IntTensor( + leftTensor.shape, + array + ) + } + + override fun StructureND.valueOrNull(): Int? = if (tensor.shape contentEquals intArrayOf(1)) + tensor.mutableBuffer.array()[tensor.bufferStart] else null + + override fun StructureND.value(): Int = valueOrNull() + ?: throw IllegalArgumentException("The tensor shape is $shape, but value method is allowed only for shape [1]") + + /** + * Constructs a tensor with the specified shape and data. + * + * @param shape the desired shape for the tensor. + * @param buffer one-dimensional data array. + * @return tensor with the [shape] shape and [buffer] data. + */ + public fun fromArray(shape: IntArray, buffer: IntArray): IntTensor { + checkEmptyShape(shape) + check(buffer.isNotEmpty()) { "Illegal empty buffer provided" } + check(buffer.size == shape.reduce(Int::times)) { + "Inconsistent shape ${shape.toList()} for buffer of size ${buffer.size} provided" + } + return IntTensor(shape, buffer, 0) + } + + /** + * Constructs a tensor with the specified shape and initializer. + * + * @param shape the desired shape for the tensor. + * @param initializer mapping tensor indices to values. + * @return tensor with the [shape] shape and data generated by the [initializer]. + */ + override fun structureND(shape: IntArray, initializer: IntRing.(IntArray) -> Int): IntTensor = fromArray( + shape, + TensorLinearStructure(shape).asSequence().map { IntRing.initializer(it) }.toMutableList().toIntArray() + ) + + override operator fun Tensor.get(i: Int): IntTensor { + val lastShape = tensor.shape.drop(1).toIntArray() + val newShape = if (lastShape.isNotEmpty()) lastShape else intArrayOf(1) + val newStart = newShape.reduce(Int::times) * i + tensor.bufferStart + return IntTensor(newShape, tensor.mutableBuffer.array(), newStart) + } + + /** + * Creates a tensor of a given shape and fills all elements with a given value. + * + * @param value the value to fill the output tensor with. + * @param shape array of integers defining the shape of the output tensor. + * @return tensor with the [shape] shape and filled with [value]. + */ + public fun full(value: Int, shape: IntArray): IntTensor { + checkEmptyShape(shape) + val buffer = IntArray(shape.reduce(Int::times)) { value } + return IntTensor(shape, buffer) + } + + /** + * Returns a tensor with the same shape as `input` filled with [value]. + * + * @param value the value to fill the output tensor with. + * @return tensor with the `input` tensor shape and filled with [value]. + */ + public fun Tensor.fullLike(value: Int): IntTensor { + val shape = tensor.shape + val buffer = IntArray(tensor.numElements) { value } + return IntTensor(shape, buffer) + } + + /** + * Returns a tensor filled with the scalar value `0`, with the shape defined by the variable argument [shape]. + * + * @param shape array of integers defining the shape of the output tensor. + * @return tensor filled with the scalar value `0`, with the [shape] shape. + */ + public fun zeros(shape: IntArray): IntTensor = full(0, shape) + + /** + * Returns a tensor filled with the scalar value `0`, with the same shape as a given array. + * + * @return tensor filled with the scalar value `0`, with the same shape as `input` tensor. + */ + public fun StructureND.zeroesLike(): IntTensor = tensor.fullLike(0) + + /** + * Returns a tensor filled with the scalar value `1`, with the shape defined by the variable argument [shape]. + * + * @param shape array of integers defining the shape of the output tensor. + * @return tensor filled with the scalar value `1`, with the [shape] shape. + */ + public fun ones(shape: IntArray): IntTensor = full(1, shape) + + /** + * Returns a tensor filled with the scalar value `1`, with the same shape as a given array. + * + * @return tensor filled with the scalar value `1`, with the same shape as `input` tensor. + */ + public fun Tensor.onesLike(): IntTensor = tensor.fullLike(1) + + /** + * Returns a 2D tensor with shape ([n], [n]), with ones on the diagonal and zeros elsewhere. + * + * @param n the number of rows and columns + * @return a 2-D tensor with ones on the diagonal and zeros elsewhere. + */ + public fun eye(n: Int): IntTensor { + val shape = intArrayOf(n, n) + val buffer = IntArray(n * n) { 0 } + val res = IntTensor(shape, buffer) + for (i in 0 until n) { + res[intArrayOf(i, i)] = 1 + } + return res + } + + /** + * Return a copy of the tensor. + * + * @return a copy of the `input` tensor with a copied buffer. + */ + public fun StructureND.copy(): IntTensor = + IntTensor(tensor.shape, tensor.mutableBuffer.array().copyOf(), tensor.bufferStart) + + override fun Int.plus(arg: StructureND): IntTensor { + val resBuffer = IntArray(arg.tensor.numElements) { i -> + arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] + this + } + return IntTensor(arg.shape, resBuffer) + } + + override fun StructureND.plus(arg: Int): IntTensor = arg + tensor + + override fun StructureND.plus(arg: StructureND): IntTensor { + checkShapesCompatible(tensor, arg.tensor) + val resBuffer = IntArray(tensor.numElements) { i -> + tensor.mutableBuffer.array()[i] + arg.tensor.mutableBuffer.array()[i] + } + return IntTensor(tensor.shape, resBuffer) + } + + override fun Tensor.plusAssign(value: Int) { + for (i in 0 until tensor.numElements) { + tensor.mutableBuffer.array()[tensor.bufferStart + i] += value + } + } + + override fun Tensor.plusAssign(arg: StructureND) { + checkShapesCompatible(tensor, arg.tensor) + for (i in 0 until tensor.numElements) { + tensor.mutableBuffer.array()[tensor.bufferStart + i] += + arg.tensor.mutableBuffer.array()[tensor.bufferStart + i] + } + } + + override fun Int.minus(arg: StructureND): IntTensor { + val resBuffer = IntArray(arg.tensor.numElements) { i -> + this - arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] + } + return IntTensor(arg.shape, resBuffer) + } + + override fun StructureND.minus(arg: Int): IntTensor { + val resBuffer = IntArray(tensor.numElements) { i -> + tensor.mutableBuffer.array()[tensor.bufferStart + i] - arg + } + return IntTensor(tensor.shape, resBuffer) + } + + override fun StructureND.minus(arg: StructureND): IntTensor { + checkShapesCompatible(tensor, arg) + val resBuffer = IntArray(tensor.numElements) { i -> + tensor.mutableBuffer.array()[i] - arg.tensor.mutableBuffer.array()[i] + } + return IntTensor(tensor.shape, resBuffer) + } + + override fun Tensor.minusAssign(value: Int) { + for (i in 0 until tensor.numElements) { + tensor.mutableBuffer.array()[tensor.bufferStart + i] -= value + } + } + + override fun Tensor.minusAssign(arg: StructureND) { + checkShapesCompatible(tensor, arg) + for (i in 0 until tensor.numElements) { + tensor.mutableBuffer.array()[tensor.bufferStart + i] -= + arg.tensor.mutableBuffer.array()[tensor.bufferStart + i] + } + } + + override fun Int.times(arg: StructureND): IntTensor { + val resBuffer = IntArray(arg.tensor.numElements) { i -> + arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] * this + } + return IntTensor(arg.shape, resBuffer) + } + + override fun StructureND.times(arg: Int): IntTensor = arg * tensor + + override fun StructureND.times(arg: StructureND): IntTensor { + checkShapesCompatible(tensor, arg) + val resBuffer = IntArray(tensor.numElements) { i -> + tensor.mutableBuffer.array()[tensor.bufferStart + i] * + arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] + } + return IntTensor(tensor.shape, resBuffer) + } + + override fun Tensor.timesAssign(value: Int) { + for (i in 0 until tensor.numElements) { + tensor.mutableBuffer.array()[tensor.bufferStart + i] *= value + } + } + + override fun Tensor.timesAssign(arg: StructureND) { + checkShapesCompatible(tensor, arg) + for (i in 0 until tensor.numElements) { + tensor.mutableBuffer.array()[tensor.bufferStart + i] *= + arg.tensor.mutableBuffer.array()[tensor.bufferStart + i] + } + } + + override fun StructureND.unaryMinus(): IntTensor { + val resBuffer = IntArray(tensor.numElements) { i -> + tensor.mutableBuffer.array()[tensor.bufferStart + i].unaryMinus() + } + return IntTensor(tensor.shape, resBuffer) + } + + override fun Tensor.transpose(i: Int, j: Int): IntTensor { + val ii = tensor.minusIndex(i) + val jj = tensor.minusIndex(j) + checkTranspose(tensor.dimension, ii, jj) + val n = tensor.numElements + val resBuffer = IntArray(n) + + val resShape = tensor.shape.copyOf() + resShape[ii] = resShape[jj].also { resShape[jj] = resShape[ii] } + + val resTensor = IntTensor(resShape, resBuffer) + + for (offset in 0 until n) { + val oldMultiIndex = tensor.indices.index(offset) + val newMultiIndex = oldMultiIndex.copyOf() + newMultiIndex[ii] = newMultiIndex[jj].also { newMultiIndex[jj] = newMultiIndex[ii] } + + val linearIndex = resTensor.indices.offset(newMultiIndex) + resTensor.mutableBuffer.array()[linearIndex] = + tensor.mutableBuffer.array()[tensor.bufferStart + offset] + } + return resTensor + } + + override fun Tensor.view(shape: IntArray): IntTensor { + checkView(tensor, shape) + return IntTensor(shape, tensor.mutableBuffer.array(), tensor.bufferStart) + } + + override fun Tensor.viewAs(other: StructureND): IntTensor = + tensor.view(other.shape) + + override fun diagonalEmbedding( + diagonalEntries: Tensor, + offset: Int, + dim1: Int, + dim2: Int, + ): IntTensor { + val n = diagonalEntries.shape.size + val d1 = minusIndexFrom(n + 1, dim1) + val d2 = minusIndexFrom(n + 1, dim2) + + check(d1 != d2) { + "Diagonal dimensions cannot be identical $d1, $d2" + } + check(d1 <= n && d2 <= n) { + "Dimension out of range" + } + + var lessDim = d1 + var greaterDim = d2 + var realOffset = offset + if (lessDim > greaterDim) { + realOffset *= -1 + lessDim = greaterDim.also { greaterDim = lessDim } + } + + val resShape = diagonalEntries.shape.slice(0 until lessDim).toIntArray() + + intArrayOf(diagonalEntries.shape[n - 1] + abs(realOffset)) + + diagonalEntries.shape.slice(lessDim until greaterDim - 1).toIntArray() + + intArrayOf(diagonalEntries.shape[n - 1] + abs(realOffset)) + + diagonalEntries.shape.slice(greaterDim - 1 until n - 1).toIntArray() + val resTensor = zeros(resShape) + + for (i in 0 until diagonalEntries.tensor.numElements) { + val multiIndex = diagonalEntries.tensor.indices.index(i) + + var offset1 = 0 + var offset2 = abs(realOffset) + if (realOffset < 0) { + offset1 = offset2.also { offset2 = offset1 } + } + val diagonalMultiIndex = multiIndex.slice(0 until lessDim).toIntArray() + + intArrayOf(multiIndex[n - 1] + offset1) + + multiIndex.slice(lessDim until greaterDim - 1).toIntArray() + + intArrayOf(multiIndex[n - 1] + offset2) + + multiIndex.slice(greaterDim - 1 until n - 1).toIntArray() + + resTensor[diagonalMultiIndex] = diagonalEntries[multiIndex] + } + + return resTensor.tensor + } + + private infix fun Tensor.eq( + other: Tensor, + ): Boolean { + checkShapesCompatible(tensor, other) + val n = tensor.numElements + if (n != other.tensor.numElements) { + return false + } + for (i in 0 until n) { + if (tensor.mutableBuffer[tensor.bufferStart + i] != other.tensor.mutableBuffer[other.tensor.bufferStart + i]) { + return false + } + } + return true + } + + /** + * Concatenates a sequence of tensors with equal shapes along the first dimension. + * + * @param tensors the [List] of tensors with same shapes to concatenate + * @return tensor with concatenation result + */ + public fun stack(tensors: List>): IntTensor { + check(tensors.isNotEmpty()) { "List must have at least 1 element" } + val shape = tensors[0].shape + check(tensors.all { it.shape contentEquals shape }) { "Tensors must have same shapes" } + val resShape = intArrayOf(tensors.size) + shape + val resBuffer = tensors.flatMap { + it.tensor.mutableBuffer.array().drop(it.tensor.bufferStart).take(it.tensor.numElements) + }.toIntArray() + return IntTensor(resShape, resBuffer, 0) + } + + /** + * Builds tensor from rows of the input tensor. + * + * @param indices the [IntArray] of 1-dimensional indices + * @return tensor with rows corresponding to row by [indices] + */ + public fun Tensor.rowsByIndices(indices: IntArray): IntTensor = stack(indices.map { this[it] }) + + private inline fun StructureND.fold(foldFunction: (IntArray) -> Int): Int = + foldFunction(tensor.copyArray()) + + private inline fun StructureND.foldDim( + dim: Int, + keepDim: Boolean, + foldFunction: (IntArray) -> R, + ): BufferedTensor { + check(dim < dimension) { "Dimension $dim out of range $dimension" } + val resShape = if (keepDim) { + shape.take(dim).toIntArray() + intArrayOf(1) + shape.takeLast(dimension - dim - 1).toIntArray() + } else { + shape.take(dim).toIntArray() + shape.takeLast(dimension - dim - 1).toIntArray() + } + val resNumElements = resShape.reduce(Int::times) + val init = foldFunction(IntArray(1) { 0 }) + val resTensor = BufferedTensor( + resShape, + MutableBuffer.auto(resNumElements) { init }, 0 + ) + for (index in resTensor.indices) { + val prefix = index.take(dim).toIntArray() + val suffix = index.takeLast(dimension - dim - 1).toIntArray() + resTensor[index] = foldFunction(IntArray(shape[dim]) { i -> + tensor[prefix + intArrayOf(i) + suffix] + }) + } + return resTensor + } + + override fun StructureND.sum(): Int = tensor.fold { it.sum() } + + override fun StructureND.sum(dim: Int, keepDim: Boolean): IntTensor = + foldDim(dim, keepDim) { x -> x.sum() }.toIntTensor() + + override fun StructureND.min(): Int = this.fold { it.minOrNull()!! } + + override fun StructureND.min(dim: Int, keepDim: Boolean): IntTensor = + foldDim(dim, keepDim) { x -> x.minOrNull()!! }.toIntTensor() + + override fun StructureND.max(): Int = this.fold { it.maxOrNull()!! } + + override fun StructureND.max(dim: Int, keepDim: Boolean): IntTensor = + foldDim(dim, keepDim) { x -> x.maxOrNull()!! }.toIntTensor() + + + override fun StructureND.argMax(dim: Int, keepDim: Boolean): IntTensor = + foldDim(dim, keepDim) { x -> + x.withIndex().maxByOrNull { it.value }?.index!! + }.toIntTensor() +} + +public val Int.Companion.tensorAlgebra: IntTensorAlgebra.Companion get() = IntTensorAlgebra +public val IntRing.tensorAlgebra: IntTensorAlgebra.Companion get() = IntTensorAlgebra + + 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 5db311db4..e997dfcca 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 @@ -16,10 +16,9 @@ internal fun checkEmptyShape(shape: IntArray) = "Illegal empty shape provided" } -internal fun checkEmptyDoubleBuffer(buffer: DoubleArray) = - check(buffer.isNotEmpty()) { - "Illegal empty buffer provided" - } +internal fun checkEmptyDoubleBuffer(buffer: DoubleArray) = check(buffer.isNotEmpty()) { + "Illegal empty buffer provided" +} internal fun checkBufferShapeConsistency(shape: IntArray, buffer: DoubleArray) = check(buffer.size == shape.reduce(Int::times)) { @@ -50,7 +49,7 @@ internal fun checkSquareMatrix(shape: IntArray) { } internal fun DoubleTensorAlgebra.checkSymmetric( - tensor: Tensor, epsilon: Double = 1e-6 + tensor: Tensor, epsilon: Double = 1e-6, ) = check(tensor.eq(tensor.transpose(), epsilon)) { "Tensor is not symmetric about the last 2 dimensions at precision $epsilon" diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt index dad4368c1..c19b8bf95 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt @@ -8,7 +8,6 @@ package space.kscience.kmath.tensors.core.internal import space.kscience.kmath.nd.MutableBufferND import space.kscience.kmath.nd.StructureND import space.kscience.kmath.structures.asMutableBuffer -import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.BufferedTensor import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.IntTensor @@ -43,7 +42,8 @@ internal val StructureND.tensor: DoubleTensor else -> this.toBufferedTensor().asTensor() } -internal val Tensor.tensor: IntTensor +@PublishedApi +internal val StructureND.tensor: IntTensor get() = when (this) { is IntTensor -> this else -> this.toBufferedTensor().asTensor() diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorAlgebraExtensions.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorAlgebraExtensions.kt index 5904e574e..619d5c753 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorAlgebraExtensions.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorAlgebraExtensions.kt @@ -13,7 +13,10 @@ import kotlin.jvm.JvmName @JvmName("varArgOne") public fun DoubleTensorAlgebra.one(vararg shape: Int): DoubleTensor = ones(intArrayOf(*shape)) + public fun DoubleTensorAlgebra.one(shape: Shape): DoubleTensor = ones(shape) + @JvmName("varArgZero") public fun DoubleTensorAlgebra.zero(vararg shape: Int): DoubleTensor = zeros(intArrayOf(*shape)) -public fun DoubleTensorAlgebra.zero(shape: Shape): DoubleTensor = zeros(shape) \ No newline at end of file + +public fun DoubleTensorAlgebra.zero(shape: Shape): DoubleTensor = zeros(shape) diff --git a/kmath-trajectory/build.gradle.kts b/kmath-trajectory/build.gradle.kts index 5ee0a241d..16a84b691 100644 --- a/kmath-trajectory/build.gradle.kts +++ b/kmath-trajectory/build.gradle.kts @@ -4,9 +4,7 @@ plugins { kscience{ native() -} - -kotlin.sourceSets.commonMain { + withContextReceivers() dependencies { api(projects.kmath.kmathGeometry) } -- 2.34.1 From a9821772dbb021f52390428cc510c182f9a1bd16 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 5 Sep 2022 22:08:35 +0300 Subject: [PATCH 178/275] Move power to ExtendedFieldOps --- .../space/kscience/kmath/nd/DoubleFieldND.kt | 12 +- .../kmath/operations/DoubleBufferOps.kt | 6 + .../kscience/kmath/operations/numbers.kt | 20 +- .../kscience/kmath/nd4j/Nd4jTensorAlgebra.kt | 1 + .../core/BroadcastDoubleTensorAlgebra.kt | 41 ++- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 320 +++++++++--------- .../kmath/tensors/core/IntTensorAlgebra.kt | 172 +++++----- .../kmath/tensors/core/internal/checks.kt | 4 +- .../tensors/core/internal/tensorCastsUtils.kt | 21 +- .../kmath/tensors/core/tensorCasts.kt | 14 +- .../kmath/tensors/core/TestDoubleTensor.kt | 10 +- 11 files changed, 320 insertions(+), 301 deletions(-) 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 4e8876731..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 @@ -11,6 +11,7 @@ import space.kscience.kmath.operations.* import space.kscience.kmath.structures.DoubleBuffer import kotlin.contracts.InvocationKind import kotlin.contracts.contract +import kotlin.math.pow import kotlin.math.pow as kpow public class DoubleBufferND( @@ -165,6 +166,15 @@ public sealed class DoubleFieldOpsND : BufferedFieldOpsND(D override fun atanh(arg: StructureND): DoubleBufferND = mapInline(arg.toBufferND()) { kotlin.math.atanh(it) } + override fun power( + arg: StructureND, + pow: Number, + ): StructureND = if (pow is Int) { + mapInline(arg.toBufferND()) { it.pow(pow) } + } else { + mapInline(arg.toBufferND()) { it.pow(pow.toDouble()) } + } + public companion object : DoubleFieldOpsND() } @@ -181,7 +191,7 @@ public class DoubleFieldND(override val shape: Shape) : it.kpow(pow) } - override fun power(arg: StructureND, pow: Number): DoubleBufferND = if(pow.isInteger()){ + override fun power(arg: StructureND, pow: Number): DoubleBufferND = if (pow.isInteger()) { power(arg, pow.toInt()) } else { val dpow = pow.toDouble() diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/DoubleBufferOps.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/DoubleBufferOps.kt index 811926c23..ded8753a3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/DoubleBufferOps.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/DoubleBufferOps.kt @@ -133,6 +133,12 @@ public abstract class DoubleBufferOps : BufferAlgebra, Exte override fun scale(a: Buffer, value: Double): DoubleBuffer = a.mapInline { it * value } + override fun power(arg: Buffer, pow: Number): Buffer = if (pow is Int) { + arg.mapInline { it.pow(pow) } + } else { + arg.mapInline { it.pow(pow.toDouble()) } + } + public companion object : DoubleBufferOps() { public inline fun Buffer.mapInline(block: (Double) -> Double): DoubleBuffer = if (this is DoubleBuffer) { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt index 16088a825..224ca1daf 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/numbers.kt @@ -2,12 +2,13 @@ * Copyright 2018-2022 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ - +@file:Suppress("NOTHING_TO_INLINE") package space.kscience.kmath.operations import space.kscience.kmath.structures.* import kotlin.math.pow as kpow + /** * Advanced Number-like semifield that implements basic operations. */ @@ -15,7 +16,8 @@ public interface ExtendedFieldOps : FieldOps, TrigonometricOperations, ExponentialOperations, - ScaleOperations { + ScaleOperations, + PowerOperations { override fun tan(arg: T): T = sin(arg) / cos(arg) override fun tanh(arg: T): T = sinh(arg) / cosh(arg) @@ -41,7 +43,7 @@ public interface ExtendedFieldOps : /** * Advanced Number-like field that implements basic operations. */ -public interface ExtendedField : ExtendedFieldOps, Field, PowerOperations, NumericAlgebra { +public interface ExtendedField : ExtendedFieldOps, Field, NumericAlgebra { override fun sinh(arg: T): T = (exp(arg) - exp(-arg)) / 2.0 override fun cosh(arg: T): T = (exp(arg) + exp(-arg)) / 2.0 override fun tanh(arg: T): T = (exp(arg) - exp(-arg)) / (exp(-arg) + exp(arg)) @@ -64,7 +66,7 @@ public interface ExtendedField : ExtendedFieldOps, Field, PowerOperatio /** * A field for [Double] without boxing. Does not produce appropriate field element. */ -@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") +@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE") public object DoubleField : ExtendedField, Norm, ScaleOperations { override val bufferFactory: MutableBufferFactory = MutableBufferFactory(::DoubleBuffer) @@ -124,7 +126,7 @@ public val Double.Companion.algebra: DoubleField get() = DoubleField /** * A field for [Float] without boxing. Does not produce appropriate field element. */ -@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") +@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE") public object FloatField : ExtendedField, Norm { override val bufferFactory: MutableBufferFactory = MutableBufferFactory(::FloatBuffer) @@ -180,7 +182,7 @@ public val Float.Companion.algebra: FloatField get() = FloatField /** * A field for [Int] without boxing. Does not produce corresponding ring element. */ -@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") +@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE") public object IntRing : Ring, Norm, NumericAlgebra { override val bufferFactory: MutableBufferFactory = MutableBufferFactory(::IntBuffer) @@ -203,7 +205,7 @@ public val Int.Companion.algebra: IntRing get() = IntRing /** * A field for [Short] without boxing. Does not produce appropriate ring element. */ -@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") +@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE") public object ShortRing : Ring, Norm, NumericAlgebra { override val bufferFactory: MutableBufferFactory = MutableBufferFactory(::ShortBuffer) @@ -226,7 +228,7 @@ public val Short.Companion.algebra: ShortRing get() = ShortRing /** * A field for [Byte] without boxing. Does not produce appropriate ring element. */ -@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") +@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE") public object ByteRing : Ring, Norm, NumericAlgebra { override val bufferFactory: MutableBufferFactory = MutableBufferFactory(::ByteBuffer) @@ -249,7 +251,7 @@ public val Byte.Companion.algebra: ByteRing get() = ByteRing /** * A field for [Double] without boxing. Does not produce appropriate ring element. */ -@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") +@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE") public object LongRing : Ring, Norm, NumericAlgebra { override val bufferFactory: MutableBufferFactory = MutableBufferFactory(::LongBuffer) 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 b6a2029e7..18068eaec 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 @@ -138,6 +138,7 @@ public sealed interface Nd4jTensorAlgebra> : AnalyticTe override fun StructureND.atan(): Nd4jArrayStructure = Transforms.atan(ndArray).wrap() override fun StructureND.tanh(): Nd4jArrayStructure = Transforms.tanh(ndArray).wrap() override fun StructureND.atanh(): Nd4jArrayStructure = Transforms.atanh(ndArray).wrap() + override fun power(arg: StructureND, pow: Number): StructureND = Transforms.pow(arg.ndArray, pow).wrap() override fun StructureND.ceil(): Nd4jArrayStructure = Transforms.ceil(ndArray).wrap() override fun StructureND.floor(): Nd4jArrayStructure = Transforms.floor(ndArray).wrap() override fun StructureND.std(dim: Int, keepDim: Boolean): Nd4jArrayStructure = diff --git a/kmath-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 fce7d30fd..31e5b6e69 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 @@ -11,7 +11,6 @@ import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.core.internal.array import space.kscience.kmath.tensors.core.internal.broadcastTensors import space.kscience.kmath.tensors.core.internal.broadcastTo -import space.kscience.kmath.tensors.core.internal.tensor /** * Basic linear algebra operations implemented with broadcasting. @@ -20,7 +19,7 @@ import space.kscience.kmath.tensors.core.internal.tensor public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun StructureND.plus(arg: StructureND): DoubleTensor { - val broadcast = broadcastTensors(tensor, arg.tensor) + val broadcast = broadcastTensors(asDoubleTensor(), arg.asDoubleTensor()) val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.indices.linearSize) { i -> @@ -30,15 +29,15 @@ 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) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] += - newOther.mutableBuffer.array()[tensor.bufferStart + i] + val newOther = broadcastTo(arg.asDoubleTensor(), asDoubleTensor().shape) + for (i in 0 until asDoubleTensor().indices.linearSize) { + asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] += + newOther.mutableBuffer.array()[asDoubleTensor().bufferStart + i] } } override fun StructureND.minus(arg: StructureND): DoubleTensor { - val broadcast = broadcastTensors(tensor, arg.tensor) + val broadcast = broadcastTensors(asDoubleTensor(), arg.asDoubleTensor()) val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.indices.linearSize) { i -> @@ -48,15 +47,15 @@ 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) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] -= - newOther.mutableBuffer.array()[tensor.bufferStart + i] + val newOther = broadcastTo(arg.asDoubleTensor(), asDoubleTensor().shape) + for (i in 0 until asDoubleTensor().indices.linearSize) { + asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] -= + newOther.mutableBuffer.array()[asDoubleTensor().bufferStart + i] } } override fun StructureND.times(arg: StructureND): DoubleTensor { - val broadcast = broadcastTensors(tensor, arg.tensor) + val broadcast = broadcastTensors(asDoubleTensor(), arg.asDoubleTensor()) val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.indices.linearSize) { i -> @@ -67,15 +66,15 @@ 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) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] *= - newOther.mutableBuffer.array()[tensor.bufferStart + i] + val newOther = broadcastTo(arg.asDoubleTensor(), asDoubleTensor().shape) + for (i in 0 until asDoubleTensor().indices.linearSize) { + asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] *= + newOther.mutableBuffer.array()[asDoubleTensor().bufferStart + i] } } override fun StructureND.div(arg: StructureND): DoubleTensor { - val broadcast = broadcastTensors(tensor, arg.tensor) + val broadcast = broadcastTensors(asDoubleTensor(), arg.asDoubleTensor()) val newThis = broadcast[0] val newOther = broadcast[1] val resBuffer = DoubleArray(newThis.indices.linearSize) { i -> @@ -86,10 +85,10 @@ 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) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] /= - newOther.mutableBuffer.array()[tensor.bufferStart + i] + val newOther = broadcastTo(arg.asDoubleTensor(), asDoubleTensor().shape) + for (i in 0 until asDoubleTensor().indices.linearSize) { + asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] /= + newOther.mutableBuffer.array()[asDoubleTensor().bufferStart + i] } } } 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 94ad3f43c..096c97324 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 @@ -43,7 +43,7 @@ public open class DoubleTensorAlgebra : @PerformancePitfall @Suppress("OVERRIDE_BY_INLINE") final override inline fun StructureND.map(transform: DoubleField.(Double) -> Double): DoubleTensor { - val tensor = this.tensor + val tensor = this.asDoubleTensor() //TODO remove additional copy val sourceArray = tensor.copyArray() val array = DoubleArray(tensor.numElements) { DoubleField.transform(sourceArray[it]) } @@ -57,7 +57,7 @@ public open class DoubleTensorAlgebra : @PerformancePitfall @Suppress("OVERRIDE_BY_INLINE") final override inline fun StructureND.mapIndexed(transform: DoubleField.(index: IntArray, Double) -> Double): DoubleTensor { - val tensor = this.tensor + val tensor = this.asDoubleTensor() //TODO remove additional copy val sourceArray = tensor.copyArray() val array = DoubleArray(tensor.numElements) { DoubleField.transform(tensor.indices.index(it), sourceArray[it]) } @@ -77,9 +77,9 @@ public open class DoubleTensorAlgebra : require(left.shape.contentEquals(right.shape)) { "The shapes in zip are not equal: left - ${left.shape}, right - ${right.shape}" } - val leftTensor = left.tensor + val leftTensor = left.asDoubleTensor() val leftArray = leftTensor.copyArray() - val rightTensor = right.tensor + val rightTensor = right.asDoubleTensor() val rightArray = rightTensor.copyArray() val array = DoubleArray(leftTensor.numElements) { DoubleField.transform(leftArray[it], rightArray[it]) } return DoubleTensor( @@ -88,8 +88,8 @@ public open class DoubleTensorAlgebra : ) } - override fun StructureND.valueOrNull(): Double? = if (tensor.shape contentEquals intArrayOf(1)) - tensor.mutableBuffer.array()[tensor.bufferStart] else null + override fun StructureND.valueOrNull(): Double? = if (asDoubleTensor().shape contentEquals intArrayOf(1)) + asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart] else null override fun StructureND.value(): Double = valueOrNull() ?: throw IllegalArgumentException("The tensor shape is $shape, but value method is allowed only for shape [1]") @@ -121,10 +121,10 @@ public open class DoubleTensorAlgebra : ) override operator fun Tensor.get(i: Int): DoubleTensor { - val lastShape = tensor.shape.drop(1).toIntArray() + val lastShape = asDoubleTensor().shape.drop(1).toIntArray() val newShape = if (lastShape.isNotEmpty()) lastShape else intArrayOf(1) - val newStart = newShape.reduce(Int::times) * i + tensor.bufferStart - return DoubleTensor(newShape, tensor.mutableBuffer.array(), newStart) + val newStart = newShape.reduce(Int::times) * i + asDoubleTensor().bufferStart + return DoubleTensor(newShape, asDoubleTensor().mutableBuffer.array(), newStart) } /** @@ -147,8 +147,8 @@ public open class DoubleTensorAlgebra : * @return tensor with the `input` tensor shape and filled with [value]. */ public fun Tensor.fullLike(value: Double): DoubleTensor { - val shape = tensor.shape - val buffer = DoubleArray(tensor.numElements) { value } + val shape = asDoubleTensor().shape + val buffer = DoubleArray(asDoubleTensor().numElements) { value } return DoubleTensor(shape, buffer) } @@ -165,7 +165,7 @@ public open class DoubleTensorAlgebra : * * @return tensor filled with the scalar value `0.0`, with the same shape as `input` tensor. */ - public fun StructureND.zeroesLike(): DoubleTensor = tensor.fullLike(0.0) + public fun StructureND.zeroesLike(): DoubleTensor = asDoubleTensor().fullLike(0.0) /** * Returns a tensor filled with the scalar value `1.0`, with the shape defined by the variable argument [shape]. @@ -180,7 +180,7 @@ public open class DoubleTensorAlgebra : * * @return tensor filled with the scalar value `1.0`, with the same shape as `input` tensor. */ - public fun Tensor.onesLike(): DoubleTensor = tensor.fullLike(1.0) + public fun Tensor.onesLike(): DoubleTensor = asDoubleTensor().fullLike(1.0) /** * Returns a 2D tensor with shape ([n], [n]), with ones on the diagonal and zeros elsewhere. @@ -204,182 +204,182 @@ public open class DoubleTensorAlgebra : * @return a copy of the `input` tensor with a copied buffer. */ public fun StructureND.copy(): DoubleTensor = - DoubleTensor(tensor.shape, tensor.mutableBuffer.array().copyOf(), tensor.bufferStart) + DoubleTensor(asDoubleTensor().shape, asDoubleTensor().mutableBuffer.array().copyOf(), asDoubleTensor().bufferStart) override fun Double.plus(arg: StructureND): DoubleTensor { - val resBuffer = DoubleArray(arg.tensor.numElements) { i -> - arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] + this + val resBuffer = DoubleArray(arg.asDoubleTensor().numElements) { i -> + arg.asDoubleTensor().mutableBuffer.array()[arg.asDoubleTensor().bufferStart + i] + this } return DoubleTensor(arg.shape, resBuffer) } - override fun StructureND.plus(arg: Double): DoubleTensor = arg + tensor + override fun StructureND.plus(arg: Double): DoubleTensor = arg + asDoubleTensor() override fun StructureND.plus(arg: StructureND): DoubleTensor { - checkShapesCompatible(tensor, arg.tensor) - val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[i] + arg.tensor.mutableBuffer.array()[i] + checkShapesCompatible(asDoubleTensor(), arg.asDoubleTensor()) + val resBuffer = DoubleArray(asDoubleTensor().numElements) { i -> + asDoubleTensor().mutableBuffer.array()[i] + arg.asDoubleTensor().mutableBuffer.array()[i] } - return DoubleTensor(tensor.shape, resBuffer) + return DoubleTensor(asDoubleTensor().shape, resBuffer) } override fun Tensor.plusAssign(value: Double) { - for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] += value + for (i in 0 until asDoubleTensor().numElements) { + asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] += value } } override fun Tensor.plusAssign(arg: StructureND) { - checkShapesCompatible(tensor, arg.tensor) - for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] += - arg.tensor.mutableBuffer.array()[tensor.bufferStart + i] + checkShapesCompatible(asDoubleTensor(), arg.asDoubleTensor()) + for (i in 0 until asDoubleTensor().numElements) { + asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] += + arg.asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] } } override fun Double.minus(arg: StructureND): DoubleTensor { - val resBuffer = DoubleArray(arg.tensor.numElements) { i -> - this - arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] + val resBuffer = DoubleArray(arg.asDoubleTensor().numElements) { i -> + this - arg.asDoubleTensor().mutableBuffer.array()[arg.asDoubleTensor().bufferStart + i] } return DoubleTensor(arg.shape, resBuffer) } override fun StructureND.minus(arg: Double): DoubleTensor { - val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[tensor.bufferStart + i] - arg + val resBuffer = DoubleArray(asDoubleTensor().numElements) { i -> + asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] - arg } - return DoubleTensor(tensor.shape, resBuffer) + return DoubleTensor(asDoubleTensor().shape, resBuffer) } override fun StructureND.minus(arg: StructureND): DoubleTensor { - checkShapesCompatible(tensor, arg) - val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[i] - arg.tensor.mutableBuffer.array()[i] + checkShapesCompatible(asDoubleTensor(), arg) + val resBuffer = DoubleArray(asDoubleTensor().numElements) { i -> + asDoubleTensor().mutableBuffer.array()[i] - arg.asDoubleTensor().mutableBuffer.array()[i] } - return DoubleTensor(tensor.shape, resBuffer) + return DoubleTensor(asDoubleTensor().shape, resBuffer) } override fun Tensor.minusAssign(value: Double) { - for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] -= value + for (i in 0 until asDoubleTensor().numElements) { + asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] -= value } } override fun Tensor.minusAssign(arg: StructureND) { - checkShapesCompatible(tensor, arg) - for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] -= - arg.tensor.mutableBuffer.array()[tensor.bufferStart + i] + checkShapesCompatible(asDoubleTensor(), arg) + for (i in 0 until asDoubleTensor().numElements) { + asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] -= + arg.asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] } } override fun Double.times(arg: StructureND): DoubleTensor { - val resBuffer = DoubleArray(arg.tensor.numElements) { i -> - arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] * this + val resBuffer = DoubleArray(arg.asDoubleTensor().numElements) { i -> + arg.asDoubleTensor().mutableBuffer.array()[arg.asDoubleTensor().bufferStart + i] * this } return DoubleTensor(arg.shape, resBuffer) } - override fun StructureND.times(arg: Double): DoubleTensor = arg * tensor + override fun StructureND.times(arg: Double): DoubleTensor = arg * asDoubleTensor() override fun StructureND.times(arg: StructureND): DoubleTensor { - checkShapesCompatible(tensor, arg) - val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[tensor.bufferStart + i] * - arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] + checkShapesCompatible(asDoubleTensor(), arg) + val resBuffer = DoubleArray(asDoubleTensor().numElements) { i -> + asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] * + arg.asDoubleTensor().mutableBuffer.array()[arg.asDoubleTensor().bufferStart + i] } - return DoubleTensor(tensor.shape, resBuffer) + return DoubleTensor(asDoubleTensor().shape, resBuffer) } override fun Tensor.timesAssign(value: Double) { - for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] *= value + for (i in 0 until asDoubleTensor().numElements) { + asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] *= value } } override fun Tensor.timesAssign(arg: StructureND) { - checkShapesCompatible(tensor, arg) - for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] *= - arg.tensor.mutableBuffer.array()[tensor.bufferStart + i] + checkShapesCompatible(asDoubleTensor(), arg) + for (i in 0 until asDoubleTensor().numElements) { + asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] *= + arg.asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] } } override fun Double.div(arg: StructureND): DoubleTensor { - val resBuffer = DoubleArray(arg.tensor.numElements) { i -> - this / arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] + val resBuffer = DoubleArray(arg.asDoubleTensor().numElements) { i -> + this / arg.asDoubleTensor().mutableBuffer.array()[arg.asDoubleTensor().bufferStart + i] } return DoubleTensor(arg.shape, resBuffer) } override fun StructureND.div(arg: Double): DoubleTensor { - val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[tensor.bufferStart + i] / arg + val resBuffer = DoubleArray(asDoubleTensor().numElements) { i -> + asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] / arg } return DoubleTensor(shape, resBuffer) } override fun StructureND.div(arg: StructureND): DoubleTensor { - checkShapesCompatible(tensor, arg) - val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] / - arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] + checkShapesCompatible(asDoubleTensor(), arg) + val resBuffer = DoubleArray(asDoubleTensor().numElements) { i -> + asDoubleTensor().mutableBuffer.array()[arg.asDoubleTensor().bufferStart + i] / + arg.asDoubleTensor().mutableBuffer.array()[arg.asDoubleTensor().bufferStart + i] } - return DoubleTensor(tensor.shape, resBuffer) + return DoubleTensor(asDoubleTensor().shape, resBuffer) } override fun Tensor.divAssign(value: Double) { - for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] /= value + for (i in 0 until asDoubleTensor().numElements) { + asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] /= value } } override fun Tensor.divAssign(arg: StructureND) { - checkShapesCompatible(tensor, arg) - for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] /= - arg.tensor.mutableBuffer.array()[tensor.bufferStart + i] + checkShapesCompatible(asDoubleTensor(), arg) + for (i in 0 until asDoubleTensor().numElements) { + asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] /= + arg.asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] } } override fun StructureND.unaryMinus(): DoubleTensor { - val resBuffer = DoubleArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[tensor.bufferStart + i].unaryMinus() + val resBuffer = DoubleArray(asDoubleTensor().numElements) { i -> + asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i].unaryMinus() } - return DoubleTensor(tensor.shape, resBuffer) + return DoubleTensor(asDoubleTensor().shape, resBuffer) } override fun Tensor.transpose(i: Int, j: Int): DoubleTensor { - val ii = tensor.minusIndex(i) - val jj = tensor.minusIndex(j) - checkTranspose(tensor.dimension, ii, jj) - val n = tensor.numElements + val ii = asDoubleTensor().minusIndex(i) + val jj = asDoubleTensor().minusIndex(j) + checkTranspose(asDoubleTensor().dimension, ii, jj) + val n = asDoubleTensor().numElements val resBuffer = DoubleArray(n) - val resShape = tensor.shape.copyOf() + val resShape = asDoubleTensor().shape.copyOf() resShape[ii] = resShape[jj].also { resShape[jj] = resShape[ii] } val resTensor = DoubleTensor(resShape, resBuffer) for (offset in 0 until n) { - val oldMultiIndex = tensor.indices.index(offset) + val oldMultiIndex = asDoubleTensor().indices.index(offset) val newMultiIndex = oldMultiIndex.copyOf() newMultiIndex[ii] = newMultiIndex[jj].also { newMultiIndex[jj] = newMultiIndex[ii] } val linearIndex = resTensor.indices.offset(newMultiIndex) resTensor.mutableBuffer.array()[linearIndex] = - tensor.mutableBuffer.array()[tensor.bufferStart + offset] + asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + offset] } return resTensor } override fun Tensor.view(shape: IntArray): DoubleTensor { - checkView(tensor, shape) - return DoubleTensor(shape, tensor.mutableBuffer.array(), tensor.bufferStart) + checkView(asDoubleTensor(), shape) + return DoubleTensor(shape, asDoubleTensor().mutableBuffer.array(), asDoubleTensor().bufferStart) } override fun Tensor.viewAs(other: StructureND): DoubleTensor = - tensor.view(other.shape) + asDoubleTensor().view(other.shape) /** * Broadcasting Matrix product of two tensors. @@ -412,25 +412,25 @@ public open class DoubleTensorAlgebra : */ @UnstableKMathAPI public infix fun StructureND.matmul(other: StructureND): DoubleTensor { - if (tensor.shape.size == 1 && other.shape.size == 1) { - return DoubleTensor(intArrayOf(1), doubleArrayOf(tensor.times(other).tensor.mutableBuffer.array().sum())) + if (asDoubleTensor().shape.size == 1 && other.shape.size == 1) { + return DoubleTensor(intArrayOf(1), doubleArrayOf(asDoubleTensor().times(other).asDoubleTensor().mutableBuffer.array().sum())) } - var newThis = tensor.copy() + var newThis = asDoubleTensor().copy() var newOther = other.copy() var penultimateDim = false var lastDim = false - if (tensor.shape.size == 1) { + if (asDoubleTensor().shape.size == 1) { penultimateDim = true - newThis = tensor.view(intArrayOf(1) + tensor.shape) + newThis = asDoubleTensor().view(intArrayOf(1) + asDoubleTensor().shape) } if (other.shape.size == 1) { lastDim = true - newOther = other.tensor.view(other.shape + intArrayOf(1)) + newOther = other.asDoubleTensor().view(other.shape + intArrayOf(1)) } - val broadcastTensors = broadcastOuterTensors(newThis.tensor, newOther.tensor) + val broadcastTensors = broadcastOuterTensors(newThis.asDoubleTensor(), newOther.asDoubleTensor()) newThis = broadcastTensors[0] newOther = broadcastTensors[1] @@ -497,8 +497,8 @@ public open class DoubleTensorAlgebra : diagonalEntries.shape.slice(greaterDim - 1 until n - 1).toIntArray() val resTensor = zeros(resShape) - for (i in 0 until diagonalEntries.tensor.numElements) { - val multiIndex = diagonalEntries.tensor.indices.index(i) + for (i in 0 until diagonalEntries.asDoubleTensor().numElements) { + val multiIndex = diagonalEntries.asDoubleTensor().indices.index(i) var offset1 = 0 var offset2 = abs(realOffset) @@ -514,7 +514,7 @@ public open class DoubleTensorAlgebra : resTensor[diagonalMultiIndex] = diagonalEntries[multiIndex] } - return resTensor.tensor + return resTensor.asDoubleTensor() } /** @@ -525,7 +525,7 @@ public open class DoubleTensorAlgebra : * @return true if two tensors have the same shape and elements, false otherwise. */ public fun Tensor.eq(other: Tensor, epsilon: Double): Boolean = - tensor.eq(other) { x, y -> abs(x - y) < epsilon } + asDoubleTensor().eq(other) { x, y -> abs(x - y) < epsilon } /** * Compares element-wise two tensors. @@ -534,21 +534,21 @@ public open class DoubleTensorAlgebra : * @param other the tensor to compare with `input` tensor. * @return true if two tensors have the same shape and elements, false otherwise. */ - public infix fun Tensor.eq(other: Tensor): Boolean = tensor.eq(other, 1e-5) + public infix fun Tensor.eq(other: Tensor): Boolean = asDoubleTensor().eq(other, 1e-5) private fun Tensor.eq( other: Tensor, eqFunction: (Double, Double) -> Boolean, ): Boolean { - checkShapesCompatible(tensor, other) - val n = tensor.numElements - if (n != other.tensor.numElements) { + checkShapesCompatible(asDoubleTensor(), other) + val n = asDoubleTensor().numElements + if (n != other.asDoubleTensor().numElements) { return false } for (i in 0 until n) { if (!eqFunction( - tensor.mutableBuffer[tensor.bufferStart + i], - other.tensor.mutableBuffer[other.tensor.bufferStart + i] + asDoubleTensor().mutableBuffer[asDoubleTensor().bufferStart + i], + other.asDoubleTensor().mutableBuffer[other.asDoubleTensor().bufferStart + i] ) ) { return false @@ -578,7 +578,7 @@ public open class DoubleTensorAlgebra : * with `0.0` mean and `1.0` standard deviation. */ public fun Tensor.randomNormalLike(seed: Long = 0): DoubleTensor = - DoubleTensor(tensor.shape, getRandomNormals(tensor.shape.reduce(Int::times), seed)) + DoubleTensor(asDoubleTensor().shape, getRandomNormals(asDoubleTensor().shape.reduce(Int::times), seed)) /** * Concatenates a sequence of tensors with equal shapes along the first dimension. @@ -592,7 +592,7 @@ public open class DoubleTensorAlgebra : check(tensors.all { it.shape contentEquals shape }) { "Tensors must have same shapes" } val resShape = intArrayOf(tensors.size) + shape val resBuffer = tensors.flatMap { - it.tensor.mutableBuffer.array().drop(it.tensor.bufferStart).take(it.tensor.numElements) + it.asDoubleTensor().mutableBuffer.array().drop(it.asDoubleTensor().bufferStart).take(it.asDoubleTensor().numElements) }.toDoubleArray() return DoubleTensor(resShape, resBuffer, 0) } @@ -606,7 +606,7 @@ public open class DoubleTensorAlgebra : public fun Tensor.rowsByIndices(indices: IntArray): DoubleTensor = stack(indices.map { this[it] }) private inline fun StructureND.fold(foldFunction: (DoubleArray) -> Double): Double = - foldFunction(tensor.copyArray()) + foldFunction(asDoubleTensor().copyArray()) private inline fun StructureND.foldDim( dim: Int, @@ -629,44 +629,44 @@ public open class DoubleTensorAlgebra : val prefix = index.take(dim).toIntArray() val suffix = index.takeLast(dimension - dim - 1).toIntArray() resTensor[index] = foldFunction(DoubleArray(shape[dim]) { i -> - tensor[prefix + intArrayOf(i) + suffix] + asDoubleTensor()[prefix + intArrayOf(i) + suffix] }) } return resTensor } - override fun StructureND.sum(): Double = tensor.fold { it.sum() } + override fun StructureND.sum(): Double = asDoubleTensor().fold { it.sum() } override fun StructureND.sum(dim: Int, keepDim: Boolean): DoubleTensor = - foldDim(dim, keepDim) { x -> x.sum() }.toDoubleTensor() + foldDim(dim, keepDim) { x -> x.sum() }.asDoubleTensor() override fun StructureND.min(): Double = this.fold { it.minOrNull()!! } override fun StructureND.min(dim: Int, keepDim: Boolean): DoubleTensor = - foldDim(dim, keepDim) { x -> x.minOrNull()!! }.toDoubleTensor() + foldDim(dim, keepDim) { x -> x.minOrNull()!! }.asDoubleTensor() override fun StructureND.max(): Double = this.fold { it.maxOrNull()!! } override fun StructureND.max(dim: Int, keepDim: Boolean): DoubleTensor = - foldDim(dim, keepDim) { x -> x.maxOrNull()!! }.toDoubleTensor() + foldDim(dim, keepDim) { x -> x.maxOrNull()!! }.asDoubleTensor() override fun StructureND.argMax(dim: Int, keepDim: Boolean): IntTensor = foldDim(dim, keepDim) { x -> x.withIndex().maxByOrNull { it.value }?.index!! - }.toIntTensor() + }.asIntTensor() - override fun StructureND.mean(): Double = this.fold { it.sum() / tensor.numElements } + override fun StructureND.mean(): Double = this.fold { it.sum() / asDoubleTensor().numElements } override fun StructureND.mean(dim: Int, keepDim: Boolean): DoubleTensor = foldDim(dim, keepDim) { arr -> check(dim < dimension) { "Dimension $dim out of range $dimension" } arr.sum() / shape[dim] - }.toDoubleTensor() + }.asDoubleTensor() override fun StructureND.std(): Double = fold { arr -> - val mean = arr.sum() / tensor.numElements - sqrt(arr.sumOf { (it - mean) * (it - mean) } / (tensor.numElements - 1)) + val mean = arr.sum() / asDoubleTensor().numElements + sqrt(arr.sumOf { (it - mean) * (it - mean) } / (asDoubleTensor().numElements - 1)) } override fun StructureND.std(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( @@ -676,11 +676,11 @@ public open class DoubleTensorAlgebra : check(dim < dimension) { "Dimension $dim out of range $dimension" } val mean = arr.sum() / shape[dim] sqrt(arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1)) - }.toDoubleTensor() + }.asDoubleTensor() override fun StructureND.variance(): Double = fold { arr -> - val mean = arr.sum() / tensor.numElements - arr.sumOf { (it - mean) * (it - mean) } / (tensor.numElements - 1) + val mean = arr.sum() / asDoubleTensor().numElements + arr.sumOf { (it - mean) * (it - mean) } / (asDoubleTensor().numElements - 1) } override fun StructureND.variance(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( @@ -690,7 +690,7 @@ public open class DoubleTensorAlgebra : check(dim < dimension) { "Dimension $dim out of range $dimension" } val mean = arr.sum() / shape[dim] arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1) - }.toDoubleTensor() + }.asDoubleTensor() private fun cov(x: DoubleTensor, y: DoubleTensor): Double { val n = x.shape[0] @@ -716,45 +716,51 @@ public open class DoubleTensorAlgebra : ) for (i in 0 until n) { for (j in 0 until n) { - resTensor[intArrayOf(i, j)] = cov(tensors[i].tensor, tensors[j].tensor) + resTensor[intArrayOf(i, j)] = cov(tensors[i].asDoubleTensor(), tensors[j].asDoubleTensor()) } } return resTensor } - override fun StructureND.exp(): DoubleTensor = tensor.map { exp(it) } + override fun StructureND.exp(): DoubleTensor = asDoubleTensor().map { exp(it) } - override fun StructureND.ln(): DoubleTensor = tensor.map { ln(it) } + override fun StructureND.ln(): DoubleTensor = asDoubleTensor().map { ln(it) } - override fun StructureND.sqrt(): DoubleTensor = tensor.map { sqrt(it) } + override fun StructureND.sqrt(): DoubleTensor = asDoubleTensor().map { sqrt(it) } - override fun StructureND.cos(): DoubleTensor = tensor.map { cos(it) } + override fun StructureND.cos(): DoubleTensor = asDoubleTensor().map { cos(it) } - override fun StructureND.acos(): DoubleTensor = tensor.map { acos(it) } + override fun StructureND.acos(): DoubleTensor = asDoubleTensor().map { acos(it) } - override fun StructureND.cosh(): DoubleTensor = tensor.map { cosh(it) } + override fun StructureND.cosh(): DoubleTensor = asDoubleTensor().map { cosh(it) } - override fun StructureND.acosh(): DoubleTensor = tensor.map { acosh(it) } + override fun StructureND.acosh(): DoubleTensor = asDoubleTensor().map { acosh(it) } - override fun StructureND.sin(): DoubleTensor = tensor.map { sin(it) } + override fun StructureND.sin(): DoubleTensor = asDoubleTensor().map { sin(it) } - override fun StructureND.asin(): DoubleTensor = tensor.map { asin(it) } + override fun StructureND.asin(): DoubleTensor = asDoubleTensor().map { asin(it) } - override fun StructureND.sinh(): DoubleTensor = tensor.map { sinh(it) } + override fun StructureND.sinh(): DoubleTensor = asDoubleTensor().map { sinh(it) } - override fun StructureND.asinh(): DoubleTensor = tensor.map { asinh(it) } + override fun StructureND.asinh(): DoubleTensor = asDoubleTensor().map { asinh(it) } - override fun StructureND.tan(): DoubleTensor = tensor.map { tan(it) } + override fun StructureND.tan(): DoubleTensor = asDoubleTensor().map { tan(it) } - override fun StructureND.atan(): DoubleTensor = tensor.map { atan(it) } + override fun StructureND.atan(): DoubleTensor = asDoubleTensor().map { atan(it) } - override fun StructureND.tanh(): DoubleTensor = tensor.map { tanh(it) } + override fun StructureND.tanh(): DoubleTensor = asDoubleTensor().map { tanh(it) } - override fun StructureND.atanh(): DoubleTensor = tensor.map { atanh(it) } + override fun StructureND.atanh(): DoubleTensor = asDoubleTensor().map { atanh(it) } - override fun StructureND.ceil(): DoubleTensor = tensor.map { ceil(it) } + override fun power(arg: StructureND, pow: Number): StructureND = if (pow is Int) { + arg.map { it.pow(pow) } + } else { + arg.map { it.pow(pow.toDouble()) } + } - override fun StructureND.floor(): DoubleTensor = tensor.map { floor(it) } + override fun StructureND.ceil(): DoubleTensor = asDoubleTensor().map { ceil(it) } + + override fun StructureND.floor(): DoubleTensor = asDoubleTensor().map { floor(it) } override fun StructureND.inv(): DoubleTensor = invLU(1e-9) @@ -770,7 +776,7 @@ public open class DoubleTensorAlgebra : * The `pivots` has the shape ``(∗, min(m, n))``. `pivots` stores all the intermediate transpositions of rows. */ public fun StructureND.luFactor(epsilon: Double): Pair = - computeLU(tensor, epsilon) + computeLU(asDoubleTensor(), epsilon) ?: throw IllegalArgumentException("Tensor contains matrices which are singular at precision $epsilon") /** @@ -809,7 +815,7 @@ public open class DoubleTensorAlgebra : val pTensor = luTensor.zeroesLike() pTensor .matrixSequence() - .zip(pivotsTensor.tensor.vectorSequence()) + .zip(pivotsTensor.asIntTensor().vectorSequence()) .forEach { (p, pivot) -> pivInit(p.as2D(), pivot.as1D(), n) } val lTensor = luTensor.zeroesLike() @@ -817,7 +823,7 @@ public open class DoubleTensorAlgebra : lTensor.matrixSequence() .zip(uTensor.matrixSequence()) - .zip(luTensor.tensor.matrixSequence()) + .zip(luTensor.asDoubleTensor().matrixSequence()) .forEach { (pairLU, lu) -> val (l, u) = pairLU luPivotHelper(l.as2D(), u.as2D(), lu.as2D(), n) @@ -841,12 +847,12 @@ public open class DoubleTensorAlgebra : */ public fun StructureND.cholesky(epsilon: Double): DoubleTensor { checkSquareMatrix(shape) - checkPositiveDefinite(tensor, epsilon) + checkPositiveDefinite(asDoubleTensor(), epsilon) val n = shape.last() val lTensor = zeroesLike() - for ((a, l) in tensor.matrixSequence().zip(lTensor.matrixSequence())) + for ((a, l) in asDoubleTensor().matrixSequence().zip(lTensor.matrixSequence())) for (i in 0 until n) choleskyHelper(a.as2D(), l.as2D(), n) return lTensor @@ -858,13 +864,13 @@ public open class DoubleTensorAlgebra : checkSquareMatrix(shape) val qTensor = zeroesLike() val rTensor = zeroesLike() - tensor.matrixSequence() + asDoubleTensor().matrixSequence() .zip( (qTensor.matrixSequence() .zip(rTensor.matrixSequence())) ).forEach { (matrix, qr) -> val (q, r) = qr - qrHelper(matrix.asTensor(), q.asTensor(), r.as2D()) + qrHelper(matrix.toTensor(), q.toTensor(), r.as2D()) } return qTensor to rTensor @@ -887,14 +893,14 @@ public open class DoubleTensorAlgebra : * @return a triple `Triple(U, S, V)`. */ public fun StructureND.svd(epsilon: Double): Triple { - val size = tensor.dimension - val commonShape = tensor.shape.sliceArray(0 until size - 2) - val (n, m) = tensor.shape.sliceArray(size - 2 until size) + val size = asDoubleTensor().dimension + val commonShape = asDoubleTensor().shape.sliceArray(0 until size - 2) + val (n, m) = asDoubleTensor().shape.sliceArray(size - 2 until size) val uTensor = zeros(commonShape + intArrayOf(min(n, m), n)) val sTensor = zeros(commonShape + intArrayOf(min(n, m))) val vTensor = zeros(commonShape + intArrayOf(min(n, m), m)) - val matrices = tensor.matrices + val matrices = asDoubleTensor().matrices val uTensors = uTensor.matrices val sTensorVectors = sTensor.vectors val vTensors = vTensor.matrices @@ -931,7 +937,7 @@ public open class DoubleTensorAlgebra : * @return a pair `eigenvalues to eigenvectors`. */ public fun StructureND.symEigSvd(epsilon: Double): Pair { - checkSymmetric(tensor, epsilon) + checkSymmetric(asDoubleTensor(), epsilon) fun MutableStructure2D.cleanSym(n: Int) { for (i in 0 until n) { @@ -945,7 +951,7 @@ public open class DoubleTensorAlgebra : } } - val (u, s, v) = tensor.svd(epsilon) + val (u, s, v) = asDoubleTensor().svd(epsilon) val shp = s.shape + intArrayOf(1) val utv = u.transpose() matmul v val n = s.shape.last() @@ -958,7 +964,7 @@ public open class DoubleTensorAlgebra : } public fun StructureND.symEigJacobi(maxIteration: Int, epsilon: Double): Pair { - checkSymmetric(tensor, epsilon) + checkSymmetric(asDoubleTensor(), epsilon) val size = this.dimension val eigenvectors = zeros(this.shape) @@ -966,7 +972,7 @@ public open class DoubleTensorAlgebra : var eigenvalueStart = 0 var eigenvectorStart = 0 - for (matrix in tensor.matrixSequence()) { + for (matrix in asDoubleTensor().matrixSequence()) { val matrix2D = matrix.as2D() val (d, v) = matrix2D.jacobiHelper(maxIteration, epsilon) @@ -1111,9 +1117,9 @@ public open class DoubleTensorAlgebra : * @return the determinant. */ public fun StructureND.detLU(epsilon: Double = 1e-9): DoubleTensor { - checkSquareMatrix(tensor.shape) - val luTensor = tensor.copy() - val pivotsTensor = tensor.setUpPivots() + checkSquareMatrix(asDoubleTensor().shape) + val luTensor = asDoubleTensor().copy() + val pivotsTensor = asDoubleTensor().setUpPivots() val n = shape.size @@ -1169,14 +1175,14 @@ public open class DoubleTensorAlgebra : * @return triple of `P`, `L` and `U` tensors. */ public fun StructureND.lu(epsilon: Double = 1e-9): Triple { - val (lu, pivots) = tensor.luFactor(epsilon) + val (lu, pivots) = asDoubleTensor().luFactor(epsilon) return luPivot(lu, pivots) } override fun StructureND.lu(): Triple = lu(1e-9) } -public val Double.Companion.tensorAlgebra: DoubleTensorAlgebra.Companion get() = DoubleTensorAlgebra -public val DoubleField.tensorAlgebra: DoubleTensorAlgebra.Companion get() = DoubleTensorAlgebra +public val Double.Companion.tensorAlgebra: DoubleTensorAlgebra get() = DoubleTensorAlgebra +public val DoubleField.tensorAlgebra: DoubleTensorAlgebra get() = DoubleTensorAlgebra diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensorAlgebra.kt index 0c8ddcf87..194f2bd18 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 @@ -39,7 +39,7 @@ public open class IntTensorAlgebra : TensorAlgebra { @PerformancePitfall @Suppress("OVERRIDE_BY_INLINE") final override inline fun StructureND.map(transform: IntRing.(Int) -> Int): IntTensor { - val tensor = this.tensor + val tensor = this.asIntTensor() //TODO remove additional copy val sourceArray = tensor.copyArray() val array = IntArray(tensor.numElements) { IntRing.transform(sourceArray[it]) } @@ -53,7 +53,7 @@ public open class IntTensorAlgebra : TensorAlgebra { @PerformancePitfall @Suppress("OVERRIDE_BY_INLINE") final override inline fun StructureND.mapIndexed(transform: IntRing.(index: IntArray, Int) -> Int): IntTensor { - val tensor = this.tensor + val tensor = this.asIntTensor() //TODO remove additional copy val sourceArray = tensor.copyArray() val array = IntArray(tensor.numElements) { IntRing.transform(tensor.indices.index(it), sourceArray[it]) } @@ -73,9 +73,9 @@ public open class IntTensorAlgebra : TensorAlgebra { require(left.shape.contentEquals(right.shape)) { "The shapes in zip are not equal: left - ${left.shape}, right - ${right.shape}" } - val leftTensor = left.tensor + val leftTensor = left.asIntTensor() val leftArray = leftTensor.copyArray() - val rightTensor = right.tensor + val rightTensor = right.asIntTensor() val rightArray = rightTensor.copyArray() val array = IntArray(leftTensor.numElements) { IntRing.transform(leftArray[it], rightArray[it]) } return IntTensor( @@ -84,8 +84,8 @@ public open class IntTensorAlgebra : TensorAlgebra { ) } - override fun StructureND.valueOrNull(): Int? = if (tensor.shape contentEquals intArrayOf(1)) - tensor.mutableBuffer.array()[tensor.bufferStart] else null + override fun StructureND.valueOrNull(): Int? = if (asIntTensor().shape contentEquals intArrayOf(1)) + asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart] else null override fun StructureND.value(): Int = valueOrNull() ?: throw IllegalArgumentException("The tensor shape is $shape, but value method is allowed only for shape [1]") @@ -119,10 +119,10 @@ public open class IntTensorAlgebra : TensorAlgebra { ) override operator fun Tensor.get(i: Int): IntTensor { - val lastShape = tensor.shape.drop(1).toIntArray() + val lastShape = asIntTensor().shape.drop(1).toIntArray() val newShape = if (lastShape.isNotEmpty()) lastShape else intArrayOf(1) - val newStart = newShape.reduce(Int::times) * i + tensor.bufferStart - return IntTensor(newShape, tensor.mutableBuffer.array(), newStart) + val newStart = newShape.reduce(Int::times) * i + asIntTensor().bufferStart + return IntTensor(newShape, asIntTensor().mutableBuffer.array(), newStart) } /** @@ -145,8 +145,8 @@ public open class IntTensorAlgebra : TensorAlgebra { * @return tensor with the `input` tensor shape and filled with [value]. */ public fun Tensor.fullLike(value: Int): IntTensor { - val shape = tensor.shape - val buffer = IntArray(tensor.numElements) { value } + val shape = asIntTensor().shape + val buffer = IntArray(asIntTensor().numElements) { value } return IntTensor(shape, buffer) } @@ -163,7 +163,7 @@ public open class IntTensorAlgebra : TensorAlgebra { * * @return tensor filled with the scalar value `0`, with the same shape as `input` tensor. */ - public fun StructureND.zeroesLike(): IntTensor = tensor.fullLike(0) + public fun StructureND.zeroesLike(): IntTensor = asIntTensor().fullLike(0) /** * Returns a tensor filled with the scalar value `1`, with the shape defined by the variable argument [shape]. @@ -178,7 +178,7 @@ public open class IntTensorAlgebra : TensorAlgebra { * * @return tensor filled with the scalar value `1`, with the same shape as `input` tensor. */ - public fun Tensor.onesLike(): IntTensor = tensor.fullLike(1) + public fun Tensor.onesLike(): IntTensor = asIntTensor().fullLike(1) /** * Returns a 2D tensor with shape ([n], [n]), with ones on the diagonal and zeros elsewhere. @@ -202,145 +202,145 @@ public open class IntTensorAlgebra : TensorAlgebra { * @return a copy of the `input` tensor with a copied buffer. */ public fun StructureND.copy(): IntTensor = - IntTensor(tensor.shape, tensor.mutableBuffer.array().copyOf(), tensor.bufferStart) + IntTensor(asIntTensor().shape, asIntTensor().mutableBuffer.array().copyOf(), asIntTensor().bufferStart) override fun Int.plus(arg: StructureND): IntTensor { - val resBuffer = IntArray(arg.tensor.numElements) { i -> - arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] + this + val resBuffer = IntArray(arg.asIntTensor().numElements) { i -> + arg.asIntTensor().mutableBuffer.array()[arg.asIntTensor().bufferStart + i] + this } return IntTensor(arg.shape, resBuffer) } - override fun StructureND.plus(arg: Int): IntTensor = arg + tensor + override fun StructureND.plus(arg: Int): IntTensor = arg + asIntTensor() override fun StructureND.plus(arg: StructureND): IntTensor { - checkShapesCompatible(tensor, arg.tensor) - val resBuffer = IntArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[i] + arg.tensor.mutableBuffer.array()[i] + checkShapesCompatible(asIntTensor(), arg.asIntTensor()) + val resBuffer = IntArray(asIntTensor().numElements) { i -> + asIntTensor().mutableBuffer.array()[i] + arg.asIntTensor().mutableBuffer.array()[i] } - return IntTensor(tensor.shape, resBuffer) + return IntTensor(asIntTensor().shape, resBuffer) } override fun Tensor.plusAssign(value: Int) { - for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] += value + for (i in 0 until asIntTensor().numElements) { + asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + i] += value } } override fun Tensor.plusAssign(arg: StructureND) { - checkShapesCompatible(tensor, arg.tensor) - for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] += - arg.tensor.mutableBuffer.array()[tensor.bufferStart + i] + checkShapesCompatible(asIntTensor(), arg.asIntTensor()) + for (i in 0 until asIntTensor().numElements) { + asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + i] += + arg.asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + i] } } override fun Int.minus(arg: StructureND): IntTensor { - val resBuffer = IntArray(arg.tensor.numElements) { i -> - this - arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] + val resBuffer = IntArray(arg.asIntTensor().numElements) { i -> + this - arg.asIntTensor().mutableBuffer.array()[arg.asIntTensor().bufferStart + i] } return IntTensor(arg.shape, resBuffer) } override fun StructureND.minus(arg: Int): IntTensor { - val resBuffer = IntArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[tensor.bufferStart + i] - arg + val resBuffer = IntArray(asIntTensor().numElements) { i -> + asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + i] - arg } - return IntTensor(tensor.shape, resBuffer) + return IntTensor(asIntTensor().shape, resBuffer) } override fun StructureND.minus(arg: StructureND): IntTensor { - checkShapesCompatible(tensor, arg) - val resBuffer = IntArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[i] - arg.tensor.mutableBuffer.array()[i] + checkShapesCompatible(asIntTensor(), arg) + val resBuffer = IntArray(asIntTensor().numElements) { i -> + asIntTensor().mutableBuffer.array()[i] - arg.asIntTensor().mutableBuffer.array()[i] } - return IntTensor(tensor.shape, resBuffer) + return IntTensor(asIntTensor().shape, resBuffer) } override fun Tensor.minusAssign(value: Int) { - for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] -= value + for (i in 0 until asIntTensor().numElements) { + asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + i] -= value } } override fun Tensor.minusAssign(arg: StructureND) { - checkShapesCompatible(tensor, arg) - for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] -= - arg.tensor.mutableBuffer.array()[tensor.bufferStart + i] + checkShapesCompatible(asIntTensor(), arg) + for (i in 0 until asIntTensor().numElements) { + asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + i] -= + arg.asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + i] } } override fun Int.times(arg: StructureND): IntTensor { - val resBuffer = IntArray(arg.tensor.numElements) { i -> - arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] * this + val resBuffer = IntArray(arg.asIntTensor().numElements) { i -> + arg.asIntTensor().mutableBuffer.array()[arg.asIntTensor().bufferStart + i] * this } return IntTensor(arg.shape, resBuffer) } - override fun StructureND.times(arg: Int): IntTensor = arg * tensor + override fun StructureND.times(arg: Int): IntTensor = arg * asIntTensor() override fun StructureND.times(arg: StructureND): IntTensor { - checkShapesCompatible(tensor, arg) - val resBuffer = IntArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[tensor.bufferStart + i] * - arg.tensor.mutableBuffer.array()[arg.tensor.bufferStart + i] + checkShapesCompatible(asIntTensor(), arg) + val resBuffer = IntArray(asIntTensor().numElements) { i -> + asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + i] * + arg.asIntTensor().mutableBuffer.array()[arg.asIntTensor().bufferStart + i] } - return IntTensor(tensor.shape, resBuffer) + return IntTensor(asIntTensor().shape, resBuffer) } override fun Tensor.timesAssign(value: Int) { - for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] *= value + for (i in 0 until asIntTensor().numElements) { + asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + i] *= value } } override fun Tensor.timesAssign(arg: StructureND) { - checkShapesCompatible(tensor, arg) - for (i in 0 until tensor.numElements) { - tensor.mutableBuffer.array()[tensor.bufferStart + i] *= - arg.tensor.mutableBuffer.array()[tensor.bufferStart + i] + checkShapesCompatible(asIntTensor(), arg) + for (i in 0 until asIntTensor().numElements) { + asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + i] *= + arg.asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + i] } } override fun StructureND.unaryMinus(): IntTensor { - val resBuffer = IntArray(tensor.numElements) { i -> - tensor.mutableBuffer.array()[tensor.bufferStart + i].unaryMinus() + val resBuffer = IntArray(asIntTensor().numElements) { i -> + asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + i].unaryMinus() } - return IntTensor(tensor.shape, resBuffer) + return IntTensor(asIntTensor().shape, resBuffer) } override fun Tensor.transpose(i: Int, j: Int): IntTensor { - val ii = tensor.minusIndex(i) - val jj = tensor.minusIndex(j) - checkTranspose(tensor.dimension, ii, jj) - val n = tensor.numElements + val ii = asIntTensor().minusIndex(i) + val jj = asIntTensor().minusIndex(j) + checkTranspose(asIntTensor().dimension, ii, jj) + val n = asIntTensor().numElements val resBuffer = IntArray(n) - val resShape = tensor.shape.copyOf() + val resShape = asIntTensor().shape.copyOf() resShape[ii] = resShape[jj].also { resShape[jj] = resShape[ii] } val resTensor = IntTensor(resShape, resBuffer) for (offset in 0 until n) { - val oldMultiIndex = tensor.indices.index(offset) + val oldMultiIndex = asIntTensor().indices.index(offset) val newMultiIndex = oldMultiIndex.copyOf() newMultiIndex[ii] = newMultiIndex[jj].also { newMultiIndex[jj] = newMultiIndex[ii] } val linearIndex = resTensor.indices.offset(newMultiIndex) resTensor.mutableBuffer.array()[linearIndex] = - tensor.mutableBuffer.array()[tensor.bufferStart + offset] + asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + offset] } return resTensor } override fun Tensor.view(shape: IntArray): IntTensor { - checkView(tensor, shape) - return IntTensor(shape, tensor.mutableBuffer.array(), tensor.bufferStart) + checkView(asIntTensor(), shape) + return IntTensor(shape, asIntTensor().mutableBuffer.array(), asIntTensor().bufferStart) } override fun Tensor.viewAs(other: StructureND): IntTensor = - tensor.view(other.shape) + asIntTensor().view(other.shape) override fun diagonalEmbedding( diagonalEntries: Tensor, @@ -374,8 +374,8 @@ public open class IntTensorAlgebra : TensorAlgebra { diagonalEntries.shape.slice(greaterDim - 1 until n - 1).toIntArray() val resTensor = zeros(resShape) - for (i in 0 until diagonalEntries.tensor.numElements) { - val multiIndex = diagonalEntries.tensor.indices.index(i) + for (i in 0 until diagonalEntries.asIntTensor().numElements) { + val multiIndex = diagonalEntries.asIntTensor().indices.index(i) var offset1 = 0 var offset2 = abs(realOffset) @@ -391,19 +391,19 @@ public open class IntTensorAlgebra : TensorAlgebra { resTensor[diagonalMultiIndex] = diagonalEntries[multiIndex] } - return resTensor.tensor + return resTensor.asIntTensor() } private infix fun Tensor.eq( other: Tensor, ): Boolean { - checkShapesCompatible(tensor, other) - val n = tensor.numElements - if (n != other.tensor.numElements) { + checkShapesCompatible(asIntTensor(), other) + val n = asIntTensor().numElements + if (n != other.asIntTensor().numElements) { return false } for (i in 0 until n) { - if (tensor.mutableBuffer[tensor.bufferStart + i] != other.tensor.mutableBuffer[other.tensor.bufferStart + i]) { + if (asIntTensor().mutableBuffer[asIntTensor().bufferStart + i] != other.asIntTensor().mutableBuffer[other.asIntTensor().bufferStart + i]) { return false } } @@ -422,7 +422,7 @@ public open class IntTensorAlgebra : TensorAlgebra { check(tensors.all { it.shape contentEquals shape }) { "Tensors must have same shapes" } val resShape = intArrayOf(tensors.size) + shape val resBuffer = tensors.flatMap { - it.tensor.mutableBuffer.array().drop(it.tensor.bufferStart).take(it.tensor.numElements) + it.asIntTensor().mutableBuffer.array().drop(it.asIntTensor().bufferStart).take(it.asIntTensor().numElements) }.toIntArray() return IntTensor(resShape, resBuffer, 0) } @@ -436,7 +436,7 @@ public open class IntTensorAlgebra : TensorAlgebra { public fun Tensor.rowsByIndices(indices: IntArray): IntTensor = stack(indices.map { this[it] }) private inline fun StructureND.fold(foldFunction: (IntArray) -> Int): Int = - foldFunction(tensor.copyArray()) + foldFunction(asIntTensor().copyArray()) private inline fun StructureND.foldDim( dim: Int, @@ -459,35 +459,35 @@ public open class IntTensorAlgebra : TensorAlgebra { val prefix = index.take(dim).toIntArray() val suffix = index.takeLast(dimension - dim - 1).toIntArray() resTensor[index] = foldFunction(IntArray(shape[dim]) { i -> - tensor[prefix + intArrayOf(i) + suffix] + asIntTensor()[prefix + intArrayOf(i) + suffix] }) } return resTensor } - override fun StructureND.sum(): Int = tensor.fold { it.sum() } + override fun StructureND.sum(): Int = asIntTensor().fold { it.sum() } override fun StructureND.sum(dim: Int, keepDim: Boolean): IntTensor = - foldDim(dim, keepDim) { x -> x.sum() }.toIntTensor() + foldDim(dim, keepDim) { x -> x.sum() }.asIntTensor() override fun StructureND.min(): Int = this.fold { it.minOrNull()!! } override fun StructureND.min(dim: Int, keepDim: Boolean): IntTensor = - foldDim(dim, keepDim) { x -> x.minOrNull()!! }.toIntTensor() + foldDim(dim, keepDim) { x -> x.minOrNull()!! }.asIntTensor() override fun StructureND.max(): Int = this.fold { it.maxOrNull()!! } override fun StructureND.max(dim: Int, keepDim: Boolean): IntTensor = - foldDim(dim, keepDim) { x -> x.maxOrNull()!! }.toIntTensor() + foldDim(dim, keepDim) { x -> x.maxOrNull()!! }.asIntTensor() override fun StructureND.argMax(dim: Int, keepDim: Boolean): IntTensor = foldDim(dim, keepDim) { x -> x.withIndex().maxByOrNull { it.value }?.index!! - }.toIntTensor() + }.asIntTensor() } -public val Int.Companion.tensorAlgebra: IntTensorAlgebra.Companion get() = IntTensorAlgebra -public val IntRing.tensorAlgebra: IntTensorAlgebra.Companion get() = IntTensorAlgebra +public val Int.Companion.tensorAlgebra: IntTensorAlgebra get() = IntTensorAlgebra +public val IntRing.tensorAlgebra: IntTensorAlgebra get() = IntTensorAlgebra diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/checks.kt index e997dfcca..62cc85396 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 @@ -58,7 +58,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.asTensor().detLU().value() > 0.0) { - "Tensor contains matrices which are not positive definite ${mat.asTensor().detLU().value()}" + check(mat.toTensor().detLU().value() > 0.0) { + "Tensor contains matrices which are not positive definite ${mat.toTensor().detLU().value()}" } } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt index c19b8bf95..e7704b257 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt @@ -13,16 +13,17 @@ import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.IntTensor import space.kscience.kmath.tensors.core.TensorLinearStructure -internal fun BufferedTensor.asTensor(): IntTensor = +internal fun BufferedTensor.toTensor(): IntTensor = IntTensor(this.shape, this.mutableBuffer.array(), this.bufferStart) -internal fun BufferedTensor.asTensor(): DoubleTensor = +internal fun BufferedTensor.toTensor(): DoubleTensor = DoubleTensor(this.shape, this.mutableBuffer.array(), this.bufferStart) internal fun StructureND.copyToBufferedTensor(): BufferedTensor = BufferedTensor( this.shape, - TensorLinearStructure(this.shape).asSequence().map(this::get).toMutableList().asMutableBuffer(), 0 + TensorLinearStructure(this.shape).asSequence().map(this::get).toMutableList().asMutableBuffer(), + 0 ) internal fun StructureND.toBufferedTensor(): BufferedTensor = when (this) { @@ -34,17 +35,3 @@ internal fun StructureND.toBufferedTensor(): BufferedTensor = when (th } else -> this.copyToBufferedTensor() } - -@PublishedApi -internal val StructureND.tensor: DoubleTensor - get() = when (this) { - is DoubleTensor -> this - else -> this.toBufferedTensor().asTensor() - } - -@PublishedApi -internal val StructureND.tensor: IntTensor - get() = when (this) { - is IntTensor -> this - else -> this.toBufferedTensor().asTensor() - } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt index 968efa468..1c914d474 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt @@ -5,18 +5,26 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.nd.StructureND import space.kscience.kmath.tensors.api.Tensor -import space.kscience.kmath.tensors.core.internal.tensor +import space.kscience.kmath.tensors.core.internal.toBufferedTensor +import space.kscience.kmath.tensors.core.internal.toTensor /** * Casts [Tensor] of [Double] to [DoubleTensor] */ -public fun Tensor.toDoubleTensor(): DoubleTensor = this.tensor +public fun StructureND.asDoubleTensor(): DoubleTensor = when (this) { + is DoubleTensor -> this + else -> this.toBufferedTensor().toTensor() +} /** * Casts [Tensor] of [Int] to [IntTensor] */ -public fun Tensor.toIntTensor(): IntTensor = this.tensor +public fun StructureND.asIntTensor(): IntTensor = when (this) { + is IntTensor -> this + else -> this.toBufferedTensor().toTensor() +} /** * Returns a copy-protected [DoubleArray] of tensor elements 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 5e5ef95be..61248cbb8 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 @@ -14,9 +14,9 @@ import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.toDoubleArray import space.kscience.kmath.tensors.core.internal.array -import space.kscience.kmath.tensors.core.internal.asTensor import space.kscience.kmath.tensors.core.internal.matrixSequence import space.kscience.kmath.tensors.core.internal.toBufferedTensor +import space.kscience.kmath.tensors.core.internal.toTensor import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue @@ -56,7 +56,7 @@ internal class TestDoubleTensor { assertEquals(tensor[intArrayOf(0, 1, 0)], 109.56) tensor.matrixSequence().forEach { - val a = it.asTensor() + val a = it.toTensor() val secondRow = a[1].as1D() val secondColumn = a.transpose(0, 1)[1].as1D() assertEquals(secondColumn[0], 77.89) @@ -75,10 +75,10 @@ internal class TestDoubleTensor { // map to tensors val bufferedTensorArray = ndArray.toBufferedTensor() // strides are flipped so data copied - val tensorArray = bufferedTensorArray.asTensor() // data not contiguous so copied again + val tensorArray = bufferedTensorArray.toTensor() // data not contiguous so copied again - val tensorArrayPublic = ndArray.toDoubleTensor() // public API, data copied twice - val sharedTensorArray = tensorArrayPublic.toDoubleTensor() // no data copied by matching type + val tensorArrayPublic = ndArray.asDoubleTensor() // public API, data copied twice + val sharedTensorArray = tensorArrayPublic.asDoubleTensor() // no data copied by matching type assertTrue(tensorArray.mutableBuffer.array() contentEquals sharedTensorArray.mutableBuffer.array()) -- 2.34.1 From 3729faf49bfde2c4158d2ac446f93a37a1057daa Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 5 Sep 2022 23:24:01 +0300 Subject: [PATCH 179/275] Rename Tensor::get to Tensor::getTensor to avoid name clash. --- .../space/kscience/kmath/tensors/PCA.kt | 6 ++--- .../tensors/linearSystemSolvingWithLUP.kt | 2 +- .../kscience/kmath/tensors/neuralNetwork.kt | 2 +- .../space/kscience/kmath/misc/cumulative.kt | 18 +++++++++++---- .../kmath/multik/MultikTensorAlgebra.kt | 8 ++++++- .../kscience/kmath/nd4j/Nd4jTensorAlgebra.kt | 5 +++- .../kmath/tensorflow/TensorFlowAlgebra.kt | 7 +++++- .../kmath/tensors/api/TensorAlgebra.kt | 21 +++++++++++++++-- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 23 +++++++++++++++---- .../kmath/tensors/core/IntTensorAlgebra.kt | 9 ++++++-- .../kmath/tensors/core/internal/linUtils.kt | 8 +++---- .../kmath/tensors/core/TestDoubleTensor.kt | 11 +++++---- 12 files changed, 90 insertions(+), 30 deletions(-) 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 c4d0ed93e..e5d1ef9f8 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt @@ -58,7 +58,7 @@ fun main(): Unit = Double.tensorAlgebra.withBroadcast { // work in context with // and find out eigenvector of it val (_, evecs) = covMatrix.symEig() - val v = evecs[0] + val v = evecs.getTensor(0) println("Eigenvector:\n$v") // reduce dimension of dataset @@ -68,7 +68,7 @@ fun main(): Unit = Double.tensorAlgebra.withBroadcast { // work in context with // we can restore original data from reduced data; // for example, find 7th element of dataset. val n = 7 - val restored = (datasetReduced[n] dot v.view(intArrayOf(1, 2))) * std + mean - println("Original value:\n${dataset[n]}") + val restored = (datasetReduced.getTensor(n) dot v.view(intArrayOf(1, 2))) * std + mean + println("Original value:\n${dataset.getTensor(n)}") println("Restored value:\n$restored") } diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt index a08fe4106..bafdf9b21 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt @@ -66,7 +66,7 @@ fun main() = Double.tensorAlgebra.withBroadcast {// work in context with linear val n = l.shape[0] val x = zeros(intArrayOf(n)) for (i in 0 until n) { - x[intArrayOf(i)] = (b[intArrayOf(i)] - l[i].dot(x).value()) / l[intArrayOf(i, i)] + x[intArrayOf(i)] = (b[intArrayOf(i)] - l.getTensor(i).dot(x).value()) / l[intArrayOf(i, i)] } return x } 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 502f6d53f..7289d86c4 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt @@ -197,7 +197,7 @@ fun main() = BroadcastDoubleTensorAlgebra { val y = fromArray( intArrayOf(sampleSize, 1), DoubleArray(sampleSize) { i -> - if (x[i].sum() > 0.0) { + if (x.getTensor(i).sum() > 0.0) { 1.0 } else { 0.0 diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt index 6ccb487c3..c05f1a6a9 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/cumulative.kt @@ -7,6 +7,7 @@ package space.kscience.kmath.misc import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.invoke +import space.kscience.kmath.structures.Buffer import kotlin.jvm.JvmName /** @@ -42,8 +43,8 @@ public inline fun List.cumulative(initial: R, crossinline operation: ( /** * Cumulative sum with custom space */ -public fun Iterable.cumulativeSum(group: Ring): Iterable = - group { cumulative(zero) { element: T, sum: T -> sum + element } } +public fun Iterable.cumulativeSum(ring: Ring): Iterable = + ring { cumulative(zero) { element: T, sum: T -> sum + element } } @JvmName("cumulativeSumOfDouble") public fun Iterable.cumulativeSum(): Iterable = cumulative(0.0) { element, sum -> sum + element } @@ -54,8 +55,8 @@ public fun Iterable.cumulativeSum(): Iterable = cumulative(0) { elemen @JvmName("cumulativeSumOfLong") public fun Iterable.cumulativeSum(): Iterable = cumulative(0L) { element, sum -> sum + element } -public fun Sequence.cumulativeSum(group: Ring): Sequence = - group { cumulative(zero) { element: T, sum: T -> sum + element } } +public fun Sequence.cumulativeSum(ring: Ring): Sequence = + ring { cumulative(zero) { element: T, sum: T -> sum + element } } @JvmName("cumulativeSumOfDouble") public fun Sequence.cumulativeSum(): Sequence = cumulative(0.0) { element, sum -> sum + element } @@ -77,3 +78,12 @@ public fun List.cumulativeSum(): List = cumulative(0) { element, sum - @JvmName("cumulativeSumOfLong") public fun List.cumulativeSum(): List = cumulative(0L) { element, sum -> sum + element } + + +public fun Buffer.cumulativeSum(ring: Ring): Buffer = with(ring) { + var accumulator: T = zero + return bufferFactory(size) { + accumulator += get(it) + accumulator + } +} diff --git a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt index c6266c985..e32221dbf 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 @@ -185,7 +185,7 @@ public abstract class MultikTensorAlgebra>( override fun StructureND.unaryMinus(): MultikTensor = asMultik().array.unaryMinus().wrap() - override fun Tensor.get(i: Int): MultikTensor = asMultik().array.mutableView(i).wrap() + override fun Tensor.getTensor(i: Int): MultikTensor = asMultik().array.mutableView(i).wrap() override fun Tensor.transpose(i: Int, j: Int): MultikTensor = asMultik().array.transpose(i, j).wrap() @@ -246,6 +246,12 @@ public abstract class MultikTensorAlgebra>( return multikMath.minDN(asMultik().array, dim).wrap() } + override fun StructureND.argMin(dim: Int, keepDim: Boolean): Tensor { + if (keepDim) TODO("keepDim not implemented") + val res = multikMath.argMinDN(asMultik().array, dim) + return with(MultikIntAlgebra(multikEngine)) { res.wrap() } + } + override fun StructureND.max(): T? = asMultik().array.max() override fun StructureND.max(dim: Int, keepDim: Boolean): Tensor { 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 18068eaec..efd3ded70 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 @@ -95,7 +95,7 @@ public sealed interface Nd4jTensorAlgebra> : AnalyticTe } override fun StructureND.unaryMinus(): Nd4jArrayStructure = ndArray.neg().wrap() - override fun Tensor.get(i: Int): Nd4jArrayStructure = ndArray.slice(i.toLong()).wrap() + override fun Tensor.getTensor(i: Int): Nd4jArrayStructure = ndArray.slice(i.toLong()).wrap() override fun Tensor.transpose(i: Int, j: Int): Nd4jArrayStructure = ndArray.swapAxes(i, j).wrap() override fun StructureND.dot(other: StructureND): Nd4jArrayStructure = ndArray.mmul(other.ndArray).wrap() @@ -111,6 +111,9 @@ public sealed interface Nd4jTensorAlgebra> : AnalyticTe override fun Tensor.view(shape: IntArray): Nd4jArrayStructure = ndArray.reshape(shape).wrap() override fun Tensor.viewAs(other: StructureND): Nd4jArrayStructure = view(other.shape) + override fun StructureND.argMin(dim: Int, keepDim: Boolean): Tensor = + ndBase.get().argmin(ndArray, keepDim, dim).asIntStructure() + override fun StructureND.argMax(dim: Int, keepDim: Boolean): Tensor = ndBase.get().argmax(ndArray, keepDim, dim).asIntStructure() 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 c6eaa7266..346750f88 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 @@ -184,7 +184,7 @@ public abstract class TensorFlowAlgebra> internal c override fun StructureND.unaryMinus(): TensorFlowOutput = operate(ops.math::neg) - override fun Tensor.get(i: Int): Tensor = operate { + override fun Tensor.getTensor(i: Int): Tensor = operate { StridedSliceHelper.stridedSlice(ops.scope(), it, Indices.at(i.toLong())) } @@ -238,6 +238,11 @@ public abstract class TensorFlowAlgebra> internal c ops.min(it, ops.constant(dim), Min.keepDims(keepDim)) } + override fun StructureND.argMin(dim: Int, keepDim: Boolean): Tensor = IntTensorFlowOutput( + graph, + ops.math.argMin(asTensorFlow().output, ops.constant(dim), TInt32::class.java).output() + ).actualTensor + override fun StructureND.max(): T = operate { ops.max(it, ops.constant(intArrayOf())) }.value() diff --git a/kmath-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 dbc42f7c7..7615af2ea 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 @@ -166,7 +166,11 @@ public interface TensorAlgebra> : RingOpsND { * @param i index of the extractable tensor * @return subtensor of the original tensor with index [i] */ - public operator fun Tensor.get(i: Int): Tensor + public fun Tensor.getTensor(i: Int): Tensor + + public fun Tensor.getTensor(first: Int, second: Int): Tensor { + return getTensor(first).getTensor(second) + } /** * Returns a tensor that is a transposed version of this tensor. The given dimensions [i] and [j] are swapped. @@ -286,6 +290,19 @@ public interface TensorAlgebra> : RingOpsND { */ public fun StructureND.min(dim: Int, keepDim: Boolean): Tensor + /** + * Returns the index of minimum value of each row of the input tensor in the given dimension [dim]. + * + * If [keepDim] is true, the output tensor is of the same size as + * input except in the dimension [dim] where it is of size 1. + * Otherwise, [dim] is squeezed, resulting in the output tensor having 1 fewer dimension. + * + * @param dim the dimension to reduce. + * @param keepDim whether the output tensor has [dim] retained or not. + * @return the index of maximum value of each row of the input tensor in the given dimension [dim]. + */ + public fun StructureND.argMin(dim: Int, keepDim: Boolean): Tensor + /** * Returns the maximum value of all elements in the input tensor or null if there are no values */ @@ -320,4 +337,4 @@ public interface TensorAlgebra> : RingOpsND { override fun add(left: StructureND, right: StructureND): Tensor = left + right override fun multiply(left: StructureND, right: StructureND): Tensor = left * right -} +} \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 096c97324..8acb15251 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 @@ -24,6 +24,7 @@ import kotlin.math.* /** * Implementation of basic operations over double tensors and basic algebra operations on them. */ +@OptIn(PerformancePitfall::class) public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra, AnalyticTensorAlgebra, @@ -120,7 +121,7 @@ public open class DoubleTensorAlgebra : TensorLinearStructure(shape).asSequence().map { DoubleField.initializer(it) }.toMutableList().toDoubleArray() ) - override operator fun Tensor.get(i: Int): DoubleTensor { + override fun Tensor.getTensor(i: Int): DoubleTensor { val lastShape = asDoubleTensor().shape.drop(1).toIntArray() val newShape = if (lastShape.isNotEmpty()) lastShape else intArrayOf(1) val newStart = newShape.reduce(Int::times) * i + asDoubleTensor().bufferStart @@ -204,7 +205,11 @@ public open class DoubleTensorAlgebra : * @return a copy of the `input` tensor with a copied buffer. */ public fun StructureND.copy(): DoubleTensor = - DoubleTensor(asDoubleTensor().shape, asDoubleTensor().mutableBuffer.array().copyOf(), asDoubleTensor().bufferStart) + DoubleTensor( + asDoubleTensor().shape, + asDoubleTensor().mutableBuffer.array().copyOf(), + asDoubleTensor().bufferStart + ) override fun Double.plus(arg: StructureND): DoubleTensor { val resBuffer = DoubleArray(arg.asDoubleTensor().numElements) { i -> @@ -413,7 +418,10 @@ public open class DoubleTensorAlgebra : @UnstableKMathAPI public infix fun StructureND.matmul(other: StructureND): DoubleTensor { if (asDoubleTensor().shape.size == 1 && other.shape.size == 1) { - return DoubleTensor(intArrayOf(1), doubleArrayOf(asDoubleTensor().times(other).asDoubleTensor().mutableBuffer.array().sum())) + return DoubleTensor( + intArrayOf(1), + doubleArrayOf(asDoubleTensor().times(other).asDoubleTensor().mutableBuffer.array().sum()) + ) } var newThis = asDoubleTensor().copy() @@ -592,7 +600,8 @@ public open class DoubleTensorAlgebra : check(tensors.all { it.shape contentEquals shape }) { "Tensors must have same shapes" } val resShape = intArrayOf(tensors.size) + shape val resBuffer = tensors.flatMap { - it.asDoubleTensor().mutableBuffer.array().drop(it.asDoubleTensor().bufferStart).take(it.asDoubleTensor().numElements) + it.asDoubleTensor().mutableBuffer.array().drop(it.asDoubleTensor().bufferStart) + .take(it.asDoubleTensor().numElements) }.toDoubleArray() return DoubleTensor(resShape, resBuffer, 0) } @@ -603,7 +612,7 @@ public open class DoubleTensorAlgebra : * @param indices the [IntArray] of 1-dimensional indices * @return tensor with rows corresponding to row by [indices] */ - public fun Tensor.rowsByIndices(indices: IntArray): DoubleTensor = stack(indices.map { this[it] }) + public fun Tensor.rowsByIndices(indices: IntArray): DoubleTensor = stack(indices.map { getTensor(it) }) private inline fun StructureND.fold(foldFunction: (DoubleArray) -> Double): Double = foldFunction(asDoubleTensor().copyArray()) @@ -645,6 +654,10 @@ public open class DoubleTensorAlgebra : override fun StructureND.min(dim: Int, keepDim: Boolean): DoubleTensor = foldDim(dim, keepDim) { x -> x.minOrNull()!! }.asDoubleTensor() + override fun StructureND.argMin(dim: Int, keepDim: Boolean): Tensor = foldDim(dim, keepDim) { x -> + x.withIndex().minByOrNull { it.value }?.index!! + }.asIntTensor() + override fun StructureND.max(): Double = this.fold { it.maxOrNull()!! } override fun StructureND.max(dim: Int, keepDim: Boolean): DoubleTensor = 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 194f2bd18..3ddbd3301 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 @@ -118,7 +118,7 @@ public open class IntTensorAlgebra : TensorAlgebra { TensorLinearStructure(shape).asSequence().map { IntRing.initializer(it) }.toMutableList().toIntArray() ) - override operator fun Tensor.get(i: Int): IntTensor { + override fun Tensor.getTensor(i: Int): IntTensor { val lastShape = asIntTensor().shape.drop(1).toIntArray() val newShape = if (lastShape.isNotEmpty()) lastShape else intArrayOf(1) val newStart = newShape.reduce(Int::times) * i + asIntTensor().bufferStart @@ -433,7 +433,7 @@ public open class IntTensorAlgebra : TensorAlgebra { * @param indices the [IntArray] of 1-dimensional indices * @return tensor with rows corresponding to row by [indices] */ - public fun Tensor.rowsByIndices(indices: IntArray): IntTensor = stack(indices.map { this[it] }) + public fun Tensor.rowsByIndices(indices: IntArray): IntTensor = stack(indices.map { getTensor(it) }) private inline fun StructureND.fold(foldFunction: (IntArray) -> Int): Int = foldFunction(asIntTensor().copyArray()) @@ -475,6 +475,11 @@ public open class IntTensorAlgebra : TensorAlgebra { override fun StructureND.min(dim: Int, keepDim: Boolean): IntTensor = foldDim(dim, keepDim) { x -> x.minOrNull()!! }.asIntTensor() + override fun StructureND.argMin(dim: Int, keepDim: Boolean): IntTensor = + foldDim(dim, keepDim) { x -> + x.withIndex().minByOrNull { it.value }?.index!! + }.asIntTensor() + override fun StructureND.max(): Int = this.fold { it.maxOrNull()!! } override fun StructureND.max(dim: Int, keepDim: Boolean): IntTensor = 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 49d67c205..ec529590f 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 @@ -257,13 +257,13 @@ internal fun DoubleTensorAlgebra.qrHelper( val qT = q.transpose(0, 1) for (j in 0 until n) { - val v = matrixT[j] + val v = matrixT.getTensor(j) val vv = v.as1D() if (j > 0) { for (i in 0 until j) { - r[i, j] = (qT[i] dot matrixT[j]).value() + r[i, j] = (qT.getTensor(i) dot matrixT.getTensor(j)).value() for (k in 0 until n) { - val qTi = qT[i].as1D() + val qTi = qT.getTensor(i).as1D() vv[k] = vv[k] - r[i, j] * qTi[k] } } @@ -313,7 +313,7 @@ internal fun DoubleTensorAlgebra.svdHelper( val outerProduct = DoubleArray(u.shape[0] * v.shape[0]) for (i in 0 until u.shape[0]) { for (j in 0 until v.shape[0]) { - outerProduct[i * v.shape[0] + j] = u[i].value() * v[j].value() + outerProduct[i * v.shape[0] + j] = u.getTensor(i).value() * v.getTensor(j).value() } } a = a - singularValue.times(DoubleTensor(intArrayOf(u.shape[0], v.shape[0]), outerProduct)) 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 61248cbb8..efdf6ba81 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 @@ -36,17 +36,18 @@ internal class TestDoubleTensor { val tensor = fromArray(intArrayOf(2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) assertEquals(tensor[intArrayOf(0, 1)], 5.8) assertTrue( - tensor.elements().map { it.second }.toList().toDoubleArray() contentEquals tensor.mutableBuffer.toDoubleArray() + tensor.elements().map { it.second }.toList() + .toDoubleArray() contentEquals tensor.mutableBuffer.toDoubleArray() ) } @Test fun testGet() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(1, 2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4)) - val matrix = tensor[0].as2D() + val matrix = tensor.getTensor(0).as2D() assertEquals(matrix[0, 1], 5.8) - val vector = tensor[0][1].as1D() + val vector = tensor.getTensor(0, 1).as1D() assertEquals(vector[0], 58.4) matrix[0, 1] = 77.89 @@ -57,8 +58,8 @@ internal class TestDoubleTensor { tensor.matrixSequence().forEach { val a = it.toTensor() - val secondRow = a[1].as1D() - val secondColumn = a.transpose(0, 1)[1].as1D() + val secondRow = a.getTensor(1).as1D() + val secondColumn = a.transpose(0, 1).getTensor(1).as1D() assertEquals(secondColumn[0], 77.89) assertEquals(secondRow[1], secondColumn[1]) } -- 2.34.1 From b5d04ba02cd325d71120819563db8a305a54688b Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 11 Sep 2022 15:27:38 +0300 Subject: [PATCH 180/275] Global refactor of tensors --- CHANGELOG.md | 1 + build.gradle.kts | 15 +- .../kscience/kmath/tensors/OLSWithSVD.kt | 2 +- .../space/kscience/kmath/tensors/PCA.kt | 2 +- .../tensors/linearSystemSolvingWithLUP.kt | 2 +- .../kscience/kmath/tensors/neuralNetwork.kt | 19 +- .../space/kscience/kmath/nd/StructureND.kt | 17 +- .../space/kscience/kmath/structures/Buffer.kt | 1 - .../kscience/kmath/structures/DoubleBuffer.kt | 5 - .../kscience/kmath/structures/IntBuffer.kt | 3 +- .../kmath/structures/NumberNDFieldTest.kt | 4 +- kmath-for-real/build.gradle.kts | 16 +- .../kscience/kmath/real/DoubleMatrixTest.kt | 2 +- .../kmath/multik/MultikTensorAlgebra.kt | 32 +- .../kscience/kmath/nd4j/Nd4jTensorAlgebra.kt | 2 +- .../kmath/tensorflow/TensorFlowAlgebra.kt | 2 +- kmath-tensors/build.gradle.kts | 6 + .../kmath/tensors/api/TensorAlgebra.kt | 2 +- .../core/BroadcastDoubleTensorAlgebra.kt | 38 +- .../kmath/tensors/core/BufferedTensor.kt | 14 +- .../kmath/tensors/core/DoubleTensor.kt | 82 ++- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 653 +++++++----------- .../kscience/kmath/tensors/core/IntTensor.kt | 88 ++- .../kmath/tensors/core/IntTensorAlgebra.kt | 307 ++++---- .../tensors/core/internal/broadcastUtils.kt | 21 +- .../kmath/tensors/core/internal/checks.kt | 17 +- .../core/internal/doubleTensorHelpers.kt | 189 +++++ .../tensors/core/internal/intTensorHelpers.kt | 64 ++ .../kmath/tensors/core/internal/linUtils.kt | 94 +-- .../tensors/core/internal/tensorCastsUtils.kt | 37 - .../kmath/tensors/core/internal/utils.kt | 35 +- .../kmath/tensors/core/tensorCasts.kt | 46 -- .../kmath/tensors/core/tensorTransform.kt | 55 ++ .../kmath/tensors/core/TestBroadcasting.kt | 29 +- .../core/TestDoubleAnalyticTensorAlgebra.kt | 87 ++- .../core/TestDoubleLinearOpsAlgebra.kt | 19 +- .../kmath/tensors/core/TestDoubleTensor.kt | 17 +- .../tensors/core/TestDoubleTensorAlgebra.kt | 108 +-- .../tensors/core/offsetBufferEquality.kt | 24 + .../src/commonMain/kotlin/bufferEquality.kt | 20 + 40 files changed, 1183 insertions(+), 994 deletions(-) create mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/doubleTensorHelpers.kt create mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/intTensorHelpers.kt delete mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt delete mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt create mode 100644 kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorTransform.kt create mode 100644 kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/offsetBufferEquality.kt create mode 100644 test-utils/src/commonMain/kotlin/bufferEquality.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index acec30836..feb925436 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Algebra now has an obligatory `bufferFactory` (#477). ### Changed +- Major refactor of tensors (only minor API changes) - Kotlin 1.7.20 - `LazyStructure` `deffered` -> `async` to comply with coroutines code style - Default `dot` operation in tensor algebra no longer support broadcasting. Instead `matmul` operation is added to `DoubleTensorAlgebra`. diff --git a/build.gradle.kts b/build.gradle.kts index 890824d65..120b0f35d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,9 +1,10 @@ +import space.kscience.gradle.isInDevelopment import space.kscience.gradle.useApache2Licence import space.kscience.gradle.useSPCTeam plugins { id("space.kscience.gradle.project") - id("org.jetbrains.kotlinx.kover") version "0.5.0" + id("org.jetbrains.kotlinx.kover") version "0.6.0" } allprojects { @@ -14,7 +15,7 @@ allprojects { } group = "space.kscience" - version = "0.3.1-dev-3" + version = "0.3.1-dev-4" } subprojects { @@ -75,8 +76,14 @@ ksciencePublish { useApache2Licence() useSPCTeam() } - github("kmath", "SciProgCentre", addToRelease = false) - space("https://maven.pkg.jetbrains.space/mipt-npm/p/sci/dev") + github("kmath", "SciProgCentre") + space( + if (isInDevelopment) { + "https://maven.pkg.jetbrains.space/mipt-npm/p/sci/dev" + } else { + "https://maven.pkg.jetbrains.space/mipt-npm/p/sci/release" + } + ) sonatype() } 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 8082ed8e2..d0b24de70 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/OLSWithSVD.kt @@ -52,7 +52,7 @@ fun main() { // inverse Sigma matrix can be restored from singular values with diagonalEmbedding function val sigma = diagonalEmbedding(singValues.map{ if (abs(it) < 1e-3) 0.0 else 1.0/it }) - val alphaOLS = v dot sigma dot u.transpose() dot y + val alphaOLS = v dot sigma dot u.transposed() dot y println("Estimated alpha:\n" + "$alphaOLS") diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt index e5d1ef9f8..1768be283 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/PCA.kt @@ -27,7 +27,7 @@ fun main(): Unit = Double.tensorAlgebra.withBroadcast { // work in context with println("y:\n$y") // stack them into single dataset - val dataset = stack(listOf(x, y)).transpose() + val dataset = stack(listOf(x, y)).transposed() // normalize both x and y val xMean = x.mean() 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 bafdf9b21..64cc138d7 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/linearSystemSolvingWithLUP.kt @@ -75,7 +75,7 @@ fun main() = Double.tensorAlgebra.withBroadcast {// work in context with linear // solveLT(l, b) function can be easily adapted for upper triangular matrix by the permutation matrix revMat // create it by placing ones on side diagonal - val revMat = u.zeroesLike() + val revMat = zeroesLike(u) val n = revMat.shape[0] for (i in 0 until n) { revMat[intArrayOf(i, n - 1 - i)] = 1.0 diff --git a/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt b/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt index 7289d86c4..84d6dcd22 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/tensors/neuralNetwork.kt @@ -3,16 +3,14 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -@file:OptIn(PerformancePitfall::class) - package space.kscience.kmath.tensors -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.operations.asIterable import space.kscience.kmath.operations.invoke import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra import space.kscience.kmath.tensors.core.DoubleTensor import space.kscience.kmath.tensors.core.DoubleTensorAlgebra -import space.kscience.kmath.tensors.core.copyArray +import space.kscience.kmath.tensors.core.toDoubleTensor import kotlin.math.sqrt const val seed = 100500L @@ -82,9 +80,9 @@ class Dense( } override fun backward(input: DoubleTensor, outputError: DoubleTensor): DoubleTensor = DoubleTensorAlgebra { - val gradInput = outputError dot weights.transpose() + val gradInput = outputError dot weights.transposed() - val gradW = input.transpose() dot outputError + val gradW = input.transposed() dot outputError val gradBias = outputError.mean(dim = 0, keepDim = false) * input.shape[0].toDouble() weights -= learningRate * gradW @@ -109,12 +107,11 @@ fun accuracy(yPred: DoubleTensor, yTrue: DoubleTensor): Double { } // neural network class -@OptIn(ExperimentalStdlibApi::class) class NeuralNetwork(private val layers: List) { private fun softMaxLoss(yPred: DoubleTensor, yTrue: DoubleTensor): DoubleTensor = BroadcastDoubleTensorAlgebra { - val onesForAnswers = yPred.zeroesLike() - yTrue.copyArray().forEachIndexed { index, labelDouble -> + val onesForAnswers = zeroesLike(yPred) + yTrue.source.asIterable().forEachIndexed { index, labelDouble -> val label = labelDouble.toInt() onesForAnswers[intArrayOf(index, label)] = 1.0 } @@ -166,7 +163,7 @@ class NeuralNetwork(private val layers: List) { for ((xBatch, yBatch) in iterBatch(xTrain, yTrain)) { train(xBatch, yBatch) } - println("Accuracy:${accuracy(yTrain, predict(xTrain).argMax(1, true).asDouble())}") + println("Accuracy:${accuracy(yTrain, predict(xTrain).argMax(1, true).toDoubleTensor())}") } } @@ -233,7 +230,7 @@ fun main() = BroadcastDoubleTensorAlgebra { val prediction = model.predict(xTest) // process raw prediction via argMax - val predictionLabels = prediction.argMax(1, true).asDouble() + val predictionLabels = prediction.argMax(1, true).toDoubleTensor() // find out accuracy val acc = accuracy(yTest, predictionLabels) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/StructureND.kt index aece10c2e..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 @@ -237,19 +237,4 @@ public interface MutableStructureND : StructureND { */ public operator fun MutableStructureND.set(vararg index: Int, value: T) { set(index, value) -} - -/** - * Transform a structure element-by element in place. - */ -@OptIn(PerformancePitfall::class) -public inline fun MutableStructureND.mapInPlace(action: (index: IntArray, t: T) -> T): Unit = - elements().forEach { (index, oldValue) -> this[index] = action(index, oldValue) } - -public inline fun StructureND.zip( - struct: StructureND, - crossinline block: (T, T) -> T, -): StructureND { - require(shape.contentEquals(struct.shape)) { "Shape mismatch in structure combination" } - return StructureND.auto(shape) { block(this[it], struct[it]) } -} +} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt index 2f9f8a8e0..5cfafe5a5 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt @@ -114,7 +114,6 @@ public interface Buffer { * * The [size] is specified, and each element is calculated by calling the specified [initializer] function. */ - @Suppress("UNCHECKED_CAST") public inline fun auto(size: Int, initializer: (Int) -> T): Buffer = auto(T::class, size, initializer) } diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBuffer.kt index e39c22158..4dd9003f3 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/DoubleBuffer.kt @@ -47,11 +47,6 @@ public inline fun DoubleBuffer(size: Int, init: (Int) -> Double): DoubleBuffer = */ public fun DoubleBuffer(vararg doubles: Double): DoubleBuffer = DoubleBuffer(doubles) -/** - * Simplified [DoubleBuffer] to array comparison - */ -public fun DoubleBuffer.contentEquals(vararg doubles: Double): Boolean = array.contentEquals(doubles) - /** * Returns a new [DoubleArray] containing all the elements of this [Buffer]. */ diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt index 8477fc13b..f80ad0ff7 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/IntBuffer.kt @@ -24,8 +24,7 @@ public value class IntBuffer(public val array: IntArray) : MutableBuffer { override operator fun iterator(): IntIterator = array.iterator() - override fun copy(): MutableBuffer = - IntBuffer(array.copyOf()) + override fun copy(): IntBuffer = IntBuffer(array.copyOf()) } /** diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt index 62c4811e8..a54af571e 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/structures/NumberNDFieldTest.kt @@ -74,7 +74,9 @@ class NumberNDFieldTest { @Test fun combineTest() { - val division = array1.zip(array2, Double::div) + algebra { + val division = zip(array1, array2) { l, r -> l / r } + } } object L2Norm : Norm, Double> { diff --git a/kmath-for-real/build.gradle.kts b/kmath-for-real/build.gradle.kts index 308b8d732..1e964d99c 100644 --- a/kmath-for-real/build.gradle.kts +++ b/kmath-for-real/build.gradle.kts @@ -2,13 +2,13 @@ plugins { id("space.kscience.gradle.mpp") } -kscience{ +kscience { native() -} - -kotlin.sourceSets.commonMain { dependencies { - api(project(":kmath-core")) + api(projects.kmathCore) + } + dependencies("commonTest") { + implementation(projects.testUtils) } } @@ -24,21 +24,21 @@ readme { feature( id = "DoubleVector", ref = "src/commonMain/kotlin/space/kscience/kmath/real/DoubleVector.kt" - ){ + ) { "Numpy-like operations for Buffers/Points" } feature( id = "DoubleMatrix", ref = "src/commonMain/kotlin/space/kscience/kmath/real/DoubleMatrix.kt" - ){ + ) { "Numpy-like operations for 2d real structures" } feature( id = "grids", ref = "src/commonMain/kotlin/space/kscience/kmath/structures/grids.kt" - ){ + ) { "Uniform grid generators" } } diff --git a/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/DoubleMatrixTest.kt b/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/DoubleMatrixTest.kt index 89e55c6d4..0d016116d 100644 --- a/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/DoubleMatrixTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/DoubleMatrixTest.kt @@ -11,7 +11,7 @@ import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.algebra -import space.kscience.kmath.structures.contentEquals +import space.kscience.kmath.testutils.contentEquals import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue diff --git a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikTensorAlgebra.kt index e32221dbf..194c5fcee 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 @@ -72,6 +72,20 @@ public abstract class MultikTensorAlgebra>( } } + /** + * Transform a structure element-by element in place. + */ + public inline fun MutableStructureND.mapIndexedInPlace(operation: (index: IntArray, t: T) -> T): Unit { + if (this is MultikTensor) { + array.multiIndices.iterator().forEach { + set(it, operation(it, get(it))) + } + } else { + indices.forEach { set(it, operation(it, get(it))) } + } + } + + @OptIn(PerformancePitfall::class) override fun zip(left: StructureND, right: StructureND, transform: A.(T, T) -> T): MultikTensor { require(left.shape.contentEquals(right.shape)) { "ND array shape mismatch" } //TODO replace by ShapeMismatchException @@ -121,7 +135,7 @@ public abstract class MultikTensorAlgebra>( if (this is MultikTensor) { array.plusAssign(value) } else { - mapInPlace { _, t -> elementAlgebra.add(t, value) } + mapIndexedInPlace { _, t -> elementAlgebra.add(t, value) } } } @@ -129,7 +143,7 @@ public abstract class MultikTensorAlgebra>( if (this is MultikTensor) { array.plusAssign(arg.asMultik().array) } else { - mapInPlace { index, t -> elementAlgebra.add(t, arg[index]) } + mapIndexedInPlace { index, t -> elementAlgebra.add(t, arg[index]) } } } @@ -145,7 +159,7 @@ public abstract class MultikTensorAlgebra>( if (this is MultikTensor) { array.minusAssign(value) } else { - mapInPlace { _, t -> elementAlgebra.run { t - value } } + mapIndexedInPlace { _, t -> elementAlgebra.run { t - value } } } } @@ -153,7 +167,7 @@ public abstract class MultikTensorAlgebra>( if (this is MultikTensor) { array.minusAssign(arg.asMultik().array) } else { - mapInPlace { index, t -> elementAlgebra.run { t - arg[index] } } + mapIndexedInPlace { index, t -> elementAlgebra.run { t - arg[index] } } } } @@ -170,7 +184,7 @@ public abstract class MultikTensorAlgebra>( if (this is MultikTensor) { array.timesAssign(value) } else { - mapInPlace { _, t -> elementAlgebra.multiply(t, value) } + mapIndexedInPlace { _, t -> elementAlgebra.multiply(t, value) } } } @@ -178,7 +192,7 @@ public abstract class MultikTensorAlgebra>( if (this is MultikTensor) { array.timesAssign(arg.asMultik().array) } else { - mapInPlace { index, t -> elementAlgebra.multiply(t, arg[index]) } + mapIndexedInPlace { index, t -> elementAlgebra.multiply(t, arg[index]) } } } @@ -187,7 +201,7 @@ public abstract class MultikTensorAlgebra>( override fun Tensor.getTensor(i: Int): MultikTensor = asMultik().array.mutableView(i).wrap() - override fun Tensor.transpose(i: Int, j: Int): MultikTensor = asMultik().array.transpose(i, j).wrap() + override fun Tensor.transposed(i: Int, j: Int): MultikTensor = asMultik().array.transpose(i, j).wrap() override fun Tensor.view(shape: IntArray): MultikTensor { require(shape.all { it > 0 }) @@ -283,7 +297,7 @@ public abstract class MultikDivisionTensorAlgebra>( if (this is MultikTensor) { array.divAssign(value) } else { - mapInPlace { _, t -> elementAlgebra.divide(t, value) } + mapIndexedInPlace { _, t -> elementAlgebra.divide(t, value) } } } @@ -291,7 +305,7 @@ public abstract class MultikDivisionTensorAlgebra>( if (this is MultikTensor) { array.divAssign(arg.asMultik().array) } else { - mapInPlace { index, t -> elementAlgebra.divide(t, arg[index]) } + mapIndexedInPlace { index, t -> elementAlgebra.divide(t, arg[index]) } } } } \ No newline at end of file diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt index efd3ded70..c1772683f 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt @@ -96,7 +96,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.transpose(i: Int, j: Int): Nd4jArrayStructure = ndArray.swapAxes(i, j).wrap() + override fun Tensor.transposed(i: Int, j: Int): Nd4jArrayStructure = ndArray.swapAxes(i, j).wrap() override fun StructureND.dot(other: StructureND): Nd4jArrayStructure = ndArray.mmul(other.ndArray).wrap() override fun StructureND.min(dim: Int, keepDim: Boolean): Nd4jArrayStructure = 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 346750f88..74fcf2d7d 100644 --- a/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/TensorFlowAlgebra.kt +++ b/kmath-tensorflow/src/main/kotlin/space/kscience/kmath/tensorflow/TensorFlowAlgebra.kt @@ -188,7 +188,7 @@ public abstract class TensorFlowAlgebra> internal c StridedSliceHelper.stridedSlice(ops.scope(), it, Indices.at(i.toLong())) } - override fun Tensor.transpose(i: Int, j: Int): Tensor = operate { + override fun Tensor.transposed(i: Int, j: Int): Tensor = operate { ops.linalg.transpose(it, ops.constant(intArrayOf(i, j))) } diff --git a/kmath-tensors/build.gradle.kts b/kmath-tensors/build.gradle.kts index 78ea4ba42..1060b37b4 100644 --- a/kmath-tensors/build.gradle.kts +++ b/kmath-tensors/build.gradle.kts @@ -25,6 +25,12 @@ kotlin.sourceSets { api(project(":kmath-stat")) } } + + commonTest{ + dependencies{ + implementation(projects.testUtils) + } + } } readme { 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 7615af2ea..70b985a54 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt @@ -180,7 +180,7 @@ public interface TensorAlgebra> : RingOpsND { * @param j the second dimension to be transposed * @return transposed tensor */ - public fun Tensor.transpose(i: Int = -2, j: Int = -1): Tensor + public fun Tensor.transposed(i: Int = -2, j: Int = -1): Tensor /** * Returns a new tensor with the same data as the self tensor but of a different shape. 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 31e5b6e69..f337a2175 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt @@ -7,8 +7,8 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.StructureND +import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.tensors.api.Tensor -import space.kscience.kmath.tensors.core.internal.array import space.kscience.kmath.tensors.core.internal.broadcastTensors import space.kscience.kmath.tensors.core.internal.broadcastTo @@ -22,8 +22,8 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val broadcast = broadcastTensors(asDoubleTensor(), arg.asDoubleTensor()) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.indices.linearSize) { i -> - newThis.mutableBuffer.array()[i] + newOther.mutableBuffer.array()[i] + val resBuffer = DoubleBuffer(newThis.indices.linearSize) { i -> + newThis.source[i] + newOther.source[i] } return DoubleTensor(newThis.shape, resBuffer) } @@ -31,8 +31,7 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { override fun Tensor.plusAssign(arg: StructureND) { val newOther = broadcastTo(arg.asDoubleTensor(), asDoubleTensor().shape) for (i in 0 until asDoubleTensor().indices.linearSize) { - asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] += - newOther.mutableBuffer.array()[asDoubleTensor().bufferStart + i] + asDoubleTensor().source[i] += newOther.source[i] } } @@ -40,17 +39,16 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val broadcast = broadcastTensors(asDoubleTensor(), arg.asDoubleTensor()) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.indices.linearSize) { i -> - newThis.mutableBuffer.array()[i] - newOther.mutableBuffer.array()[i] + val resBuffer = DoubleBuffer(newThis.indices.linearSize) { i -> + newThis.source[i] - newOther.source[i] } return DoubleTensor(newThis.shape, resBuffer) } override fun Tensor.minusAssign(arg: StructureND) { val newOther = broadcastTo(arg.asDoubleTensor(), asDoubleTensor().shape) - for (i in 0 until asDoubleTensor().indices.linearSize) { - asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] -= - newOther.mutableBuffer.array()[asDoubleTensor().bufferStart + i] + for (i in 0 until indices.linearSize) { + asDoubleTensor().source[i] -= newOther.source[i] } } @@ -58,18 +56,16 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val broadcast = broadcastTensors(asDoubleTensor(), arg.asDoubleTensor()) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.indices.linearSize) { i -> - newThis.mutableBuffer.array()[newThis.bufferStart + i] * - newOther.mutableBuffer.array()[newOther.bufferStart + i] + val resBuffer = DoubleBuffer(newThis.indices.linearSize) { i -> + newThis.source[i] * newOther.source[i] } return DoubleTensor(newThis.shape, resBuffer) } override fun Tensor.timesAssign(arg: StructureND) { val newOther = broadcastTo(arg.asDoubleTensor(), asDoubleTensor().shape) - for (i in 0 until asDoubleTensor().indices.linearSize) { - asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] *= - newOther.mutableBuffer.array()[asDoubleTensor().bufferStart + i] + for (i in 0 until indices.linearSize) { + asDoubleTensor().source[+i] *= newOther.source[i] } } @@ -77,18 +73,16 @@ public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() { val broadcast = broadcastTensors(asDoubleTensor(), arg.asDoubleTensor()) val newThis = broadcast[0] val newOther = broadcast[1] - val resBuffer = DoubleArray(newThis.indices.linearSize) { i -> - newThis.mutableBuffer.array()[newOther.bufferStart + i] / - newOther.mutableBuffer.array()[newOther.bufferStart + i] + val resBuffer = DoubleBuffer(newThis.indices.linearSize) { i -> + newThis.source[i] / newOther.source[i] } return DoubleTensor(newThis.shape, resBuffer) } override fun Tensor.divAssign(arg: StructureND) { val newOther = broadcastTo(arg.asDoubleTensor(), asDoubleTensor().shape) - for (i in 0 until asDoubleTensor().indices.linearSize) { - asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] /= - newOther.mutableBuffer.array()[asDoubleTensor().bufferStart + i] + for (i in 0 until indices.linearSize) { + asDoubleTensor().source[i] /= newOther.source[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 98e6ab430..0b043db56 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BufferedTensor.kt @@ -13,12 +13,12 @@ import space.kscience.kmath.tensors.api.Tensor /** * Represents [Tensor] over a [MutableBuffer] intended to be used through [DoubleTensor] and [IntTensor] */ -public open class BufferedTensor internal constructor( +public abstract class BufferedTensor( override val shape: IntArray, - @PublishedApi internal val mutableBuffer: MutableBuffer, - @PublishedApi internal val bufferStart: Int, ) : Tensor { + public abstract val source: MutableBuffer + /** * Buffer strides based on [TensorLinearStructure] implementation */ @@ -27,14 +27,8 @@ public open class BufferedTensor internal constructor( /** * Number of elements in tensor */ - public val numElements: Int - get() = indices.linearSize + public val linearSize: Int get() = indices.linearSize - override fun get(index: IntArray): T = mutableBuffer[bufferStart + indices.offset(index)] - - override fun set(index: IntArray, value: T) { - mutableBuffer[bufferStart + indices.offset(index)] = value - } @PerformancePitfall override fun elements(): Sequence> = indices.asSequence().map { diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt index e8239caf4..e9589eb0a 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensor.kt @@ -5,16 +5,88 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.core.internal.toPrettyString +public class OffsetDoubleBuffer( + private val source: DoubleBuffer, + private val offset: Int, + override val size: Int, +) : MutableBuffer { + + init { + require(offset >= 0) { "Offset must be non-negative" } + require(size >= 0) { "Size must be non-negative" } + require(offset + size <= source.size) { "Maximum index must be inside source dimension" } + } + + override fun set(index: Int, value: Double) { + require(index in 0 until size) { "Index must be in [0, size)" } + source[index + offset] = value + } + + override fun get(index: Int): Double = source[index + offset] + + /** + * Copy only a part of buffer that belongs to this tensor + */ + override fun copy(): DoubleBuffer = source.array.copyOfRange(offset, offset + size).asBuffer() + + override fun iterator(): Iterator = iterator { + for (i in indices) { + yield(get(i)) + } + } + + override fun toString(): String = Buffer.toString(this) + + public fun view(addOffset: Int, newSize: Int = size - addOffset): OffsetDoubleBuffer = + OffsetDoubleBuffer(source, offset + addOffset, newSize) +} + +public fun OffsetDoubleBuffer.slice(range: IntRange): OffsetDoubleBuffer = view(range.first, range.last - range.first) + +/** + * Map only operable content of the offset buffer + */ +public inline fun OffsetDoubleBuffer.map(operation: (Double) -> Double): DoubleBuffer = + DoubleBuffer(size) { operation(get(it)) } + +public inline fun OffsetDoubleBuffer.zip( + other: OffsetDoubleBuffer, + operation: (l: Double, r: Double) -> Double, +): DoubleBuffer { + require(size == other.size) { "The sizes of zipped buffers must be the same" } + return DoubleBuffer(size) { operation(get(it), other[it]) } +} + +/** + * map in place + */ +public inline fun OffsetDoubleBuffer.mapInPlace(operation: (Double) -> Double) { + indices.forEach { set(it, operation(get(it))) } +} + /** * Default [BufferedTensor] implementation for [Double] values */ -public class DoubleTensor @PublishedApi internal constructor( +public class DoubleTensor( shape: IntArray, - buffer: DoubleArray, - offset: Int = 0 -) : BufferedTensor(shape, DoubleBuffer(buffer), offset) { + override val source: OffsetDoubleBuffer, +) : BufferedTensor(shape) { + + init { + require(linearSize == source.size) { "Source buffer size must be equal tensor size" } + } + + public constructor(shape: IntArray, buffer: DoubleBuffer) : this(shape, OffsetDoubleBuffer(buffer, 0, buffer.size)) + + override fun get(index: IntArray): Double = this.source[indices.offset(index)] + + override fun set(index: IntArray, value: Double) { + source[indices.offset(index)] = value + } + + override fun toString(): String = toPrettyString() } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt index 8acb15251..d758c49a1 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 @@ -12,8 +12,7 @@ import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.* import space.kscience.kmath.operations.DoubleField -import space.kscience.kmath.structures.MutableBuffer -import space.kscience.kmath.structures.indices +import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.api.AnalyticTensorAlgebra import space.kscience.kmath.tensors.api.LinearOpsTensorAlgebra import space.kscience.kmath.tensors.api.Tensor @@ -41,56 +40,64 @@ public open class DoubleTensorAlgebra : * @param transform the function to be applied to each element of the tensor. * @return the resulting tensor after applying the function. */ - @PerformancePitfall @Suppress("OVERRIDE_BY_INLINE") final override inline fun StructureND.map(transform: DoubleField.(Double) -> Double): DoubleTensor { - val tensor = this.asDoubleTensor() + val tensor = asDoubleTensor() //TODO remove additional copy - val sourceArray = tensor.copyArray() - val array = DoubleArray(tensor.numElements) { DoubleField.transform(sourceArray[it]) } + val array = DoubleBuffer(tensor.source.size) { DoubleField.transform(tensor.source[it]) } return DoubleTensor( tensor.shape, array, - tensor.bufferStart ) } - @PerformancePitfall + public inline fun Tensor.mapInPlace(operation: (Double) -> Double) { + if (this is DoubleTensor) { + source.mapInPlace(operation) + } else { + indices.forEach { set(it, operation(get(it))) } + } + } + + public inline fun Tensor.mapIndexedInPlace(operation: (IntArray, Double) -> Double) { + indices.forEach { set(it, operation(it, get(it))) } + } + @Suppress("OVERRIDE_BY_INLINE") final override inline fun StructureND.mapIndexed(transform: DoubleField.(index: IntArray, Double) -> Double): DoubleTensor { val tensor = this.asDoubleTensor() //TODO remove additional copy - val sourceArray = tensor.copyArray() - val array = DoubleArray(tensor.numElements) { DoubleField.transform(tensor.indices.index(it), sourceArray[it]) } - return DoubleTensor( - tensor.shape, - array, - tensor.bufferStart - ) + val buffer = DoubleBuffer(tensor.source.size) { + DoubleField.transform(tensor.indices.index(it), tensor.source[it]) + } + return DoubleTensor(tensor.shape, buffer) } - @PerformancePitfall - override fun zip( + @Suppress("OVERRIDE_BY_INLINE") + final override inline fun zip( left: StructureND, right: StructureND, transform: DoubleField.(Double, Double) -> Double, ): DoubleTensor { - require(left.shape.contentEquals(right.shape)) { - "The shapes in zip are not equal: left - ${left.shape}, right - ${right.shape}" - } + checkShapesCompatible(left, right) + val leftTensor = left.asDoubleTensor() - val leftArray = leftTensor.copyArray() val rightTensor = right.asDoubleTensor() - val rightArray = rightTensor.copyArray() - val array = DoubleArray(leftTensor.numElements) { DoubleField.transform(leftArray[it], rightArray[it]) } - return DoubleTensor( - leftTensor.shape, - array - ) + val buffer = DoubleBuffer(leftTensor.source.size) { + DoubleField.transform(leftTensor.source[it], rightTensor.source[it]) + } + return DoubleTensor(leftTensor.shape, buffer) } - override fun StructureND.valueOrNull(): Double? = if (asDoubleTensor().shape contentEquals intArrayOf(1)) - asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart] else null + + public inline fun StructureND.reduceElements(transform: (DoubleBuffer) -> Double): Double = + transform(asDoubleTensor().source.copy()) + //TODO do we need protective copy? + + override fun StructureND.valueOrNull(): Double? { + val dt = asDoubleTensor() + return if (dt.shape contentEquals intArrayOf(1)) dt.source[0] else null + } override fun StructureND.value(): Double = valueOrNull() ?: throw IllegalArgumentException("The tensor shape is $shape, but value method is allowed only for shape [1]") @@ -99,14 +106,14 @@ public open class DoubleTensorAlgebra : * Constructs a tensor with the specified shape and data. * * @param shape the desired shape for the tensor. - * @param buffer one-dimensional data array. - * @return tensor with the [shape] shape and [buffer] data. + * @param array one-dimensional data array. + * @return tensor with the [shape] shape and [array] data. */ - public fun fromArray(shape: IntArray, buffer: DoubleArray): DoubleTensor { - checkEmptyShape(shape) - checkEmptyDoubleBuffer(buffer) - checkBufferShapeConsistency(shape, buffer) - return DoubleTensor(shape, buffer, 0) + public fun fromArray(shape: IntArray, array: DoubleArray): DoubleTensor { + checkNotEmptyShape(shape) + checkEmptyDoubleBuffer(array) + checkBufferShapeConsistency(shape, array) + return DoubleTensor(shape, array.asBuffer()) } /** @@ -122,10 +129,10 @@ public open class DoubleTensorAlgebra : ) override fun Tensor.getTensor(i: Int): DoubleTensor { - val lastShape = asDoubleTensor().shape.drop(1).toIntArray() + val dt = asDoubleTensor() + val lastShape = shape.drop(1).toIntArray() val newShape = if (lastShape.isNotEmpty()) lastShape else intArrayOf(1) - val newStart = newShape.reduce(Int::times) * i + asDoubleTensor().bufferStart - return DoubleTensor(newShape, asDoubleTensor().mutableBuffer.array(), newStart) + return DoubleTensor(newShape, dt.source.view(newShape.reduce(Int::times) * i)) } /** @@ -136,8 +143,8 @@ public open class DoubleTensorAlgebra : * @return tensor with the [shape] shape and filled with [value]. */ public fun full(value: Double, shape: IntArray): DoubleTensor { - checkEmptyShape(shape) - val buffer = DoubleArray(shape.reduce(Int::times)) { value } + checkNotEmptyShape(shape) + val buffer = DoubleBuffer(shape.reduce(Int::times)) { value } return DoubleTensor(shape, buffer) } @@ -147,9 +154,9 @@ public open class DoubleTensorAlgebra : * @param value the value to fill the output tensor with. * @return tensor with the `input` tensor shape and filled with [value]. */ - public fun Tensor.fullLike(value: Double): DoubleTensor { - val shape = asDoubleTensor().shape - val buffer = DoubleArray(asDoubleTensor().numElements) { value } + public fun fullLike(structureND: StructureND<*>, value: Double): DoubleTensor { + val shape = structureND.shape + val buffer = DoubleBuffer(structureND.indices.linearSize) { value } return DoubleTensor(shape, buffer) } @@ -166,7 +173,7 @@ public open class DoubleTensorAlgebra : * * @return tensor filled with the scalar value `0.0`, with the same shape as `input` tensor. */ - public fun StructureND.zeroesLike(): DoubleTensor = asDoubleTensor().fullLike(0.0) + public fun zeroesLike(structureND: StructureND<*>): DoubleTensor = fullLike(structureND, 0.0) /** * Returns a tensor filled with the scalar value `1.0`, with the shape defined by the variable argument [shape]. @@ -181,7 +188,7 @@ public open class DoubleTensorAlgebra : * * @return tensor filled with the scalar value `1.0`, with the same shape as `input` tensor. */ - public fun Tensor.onesLike(): DoubleTensor = asDoubleTensor().fullLike(1.0) + public fun onesLike(structureND: StructureND<*>): DoubleTensor = fullLike(structureND, 1.0) /** * Returns a 2D tensor with shape ([n], [n]), with ones on the diagonal and zeros elsewhere. @@ -191,7 +198,7 @@ public open class DoubleTensorAlgebra : */ public fun eye(n: Int): DoubleTensor { val shape = intArrayOf(n, n) - val buffer = DoubleArray(n * n) { 0.0 } + val buffer = DoubleBuffer(n * n) { 0.0 } val res = DoubleTensor(shape, buffer) for (i in 0 until n) { res[intArrayOf(i, i)] = 1.0 @@ -199,192 +206,102 @@ public open class DoubleTensorAlgebra : return res } - /** - * Return a copy of the tensor. - * - * @return a copy of the `input` tensor with a copied buffer. - */ - public fun StructureND.copy(): DoubleTensor = - DoubleTensor( - asDoubleTensor().shape, - asDoubleTensor().mutableBuffer.array().copyOf(), - asDoubleTensor().bufferStart - ) + override fun Double.plus(arg: StructureND): DoubleTensor = arg.map { this@plus + it } - override fun Double.plus(arg: StructureND): DoubleTensor { - val resBuffer = DoubleArray(arg.asDoubleTensor().numElements) { i -> - arg.asDoubleTensor().mutableBuffer.array()[arg.asDoubleTensor().bufferStart + i] + this - } - return DoubleTensor(arg.shape, resBuffer) - } + override fun StructureND.plus(arg: Double): DoubleTensor = map { it + arg } - override fun StructureND.plus(arg: Double): DoubleTensor = arg + asDoubleTensor() - - override fun StructureND.plus(arg: StructureND): DoubleTensor { - checkShapesCompatible(asDoubleTensor(), arg.asDoubleTensor()) - val resBuffer = DoubleArray(asDoubleTensor().numElements) { i -> - asDoubleTensor().mutableBuffer.array()[i] + arg.asDoubleTensor().mutableBuffer.array()[i] - } - return DoubleTensor(asDoubleTensor().shape, resBuffer) - } + override fun StructureND.plus(arg: StructureND): DoubleTensor = zip(this, arg) { l, r -> l + r } override fun Tensor.plusAssign(value: Double) { - for (i in 0 until asDoubleTensor().numElements) { - asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] += value - } + mapInPlace { it + value } } override fun Tensor.plusAssign(arg: StructureND) { checkShapesCompatible(asDoubleTensor(), arg.asDoubleTensor()) - for (i in 0 until asDoubleTensor().numElements) { - asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] += - arg.asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] + mapIndexedInPlace { index, value -> + value + arg[index] } } - override fun Double.minus(arg: StructureND): DoubleTensor { - val resBuffer = DoubleArray(arg.asDoubleTensor().numElements) { i -> - this - arg.asDoubleTensor().mutableBuffer.array()[arg.asDoubleTensor().bufferStart + i] - } - return DoubleTensor(arg.shape, resBuffer) - } + override fun Double.minus(arg: StructureND): DoubleTensor = arg.map { this@minus - it } - override fun StructureND.minus(arg: Double): DoubleTensor { - val resBuffer = DoubleArray(asDoubleTensor().numElements) { i -> - asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] - arg - } - return DoubleTensor(asDoubleTensor().shape, resBuffer) - } + override fun StructureND.minus(arg: Double): DoubleTensor = map { it - arg } - override fun StructureND.minus(arg: StructureND): DoubleTensor { - checkShapesCompatible(asDoubleTensor(), arg) - val resBuffer = DoubleArray(asDoubleTensor().numElements) { i -> - asDoubleTensor().mutableBuffer.array()[i] - arg.asDoubleTensor().mutableBuffer.array()[i] - } - return DoubleTensor(asDoubleTensor().shape, resBuffer) - } + override fun StructureND.minus(arg: StructureND): DoubleTensor = zip(this, arg) { l, r -> l + r } override fun Tensor.minusAssign(value: Double) { - for (i in 0 until asDoubleTensor().numElements) { - asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] -= value - } + mapInPlace { it - value } } override fun Tensor.minusAssign(arg: StructureND) { - checkShapesCompatible(asDoubleTensor(), arg) - for (i in 0 until asDoubleTensor().numElements) { - asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] -= - arg.asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] - } + checkShapesCompatible(this, arg) + mapIndexedInPlace { index, value -> value - arg[index] } } - override fun Double.times(arg: StructureND): DoubleTensor { - val resBuffer = DoubleArray(arg.asDoubleTensor().numElements) { i -> - arg.asDoubleTensor().mutableBuffer.array()[arg.asDoubleTensor().bufferStart + i] * this - } - return DoubleTensor(arg.shape, resBuffer) - } + override fun Double.times(arg: StructureND): DoubleTensor = arg.map { this@times * it } override fun StructureND.times(arg: Double): DoubleTensor = arg * asDoubleTensor() - override fun StructureND.times(arg: StructureND): DoubleTensor { - checkShapesCompatible(asDoubleTensor(), arg) - val resBuffer = DoubleArray(asDoubleTensor().numElements) { i -> - asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] * - arg.asDoubleTensor().mutableBuffer.array()[arg.asDoubleTensor().bufferStart + i] - } - return DoubleTensor(asDoubleTensor().shape, resBuffer) - } + override fun StructureND.times(arg: StructureND): DoubleTensor = zip(this, arg) { l, r -> l * r } override fun Tensor.timesAssign(value: Double) { - for (i in 0 until asDoubleTensor().numElements) { - asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] *= value - } + mapInPlace { it * value } } override fun Tensor.timesAssign(arg: StructureND) { - checkShapesCompatible(asDoubleTensor(), arg) - for (i in 0 until asDoubleTensor().numElements) { - asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] *= - arg.asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] - } + checkShapesCompatible(this, arg) + mapIndexedInPlace { index, value -> value * arg[index] } } - override fun Double.div(arg: StructureND): DoubleTensor { - val resBuffer = DoubleArray(arg.asDoubleTensor().numElements) { i -> - this / arg.asDoubleTensor().mutableBuffer.array()[arg.asDoubleTensor().bufferStart + i] - } - return DoubleTensor(arg.shape, resBuffer) - } + override fun Double.div(arg: StructureND): DoubleTensor = arg.map { this@div / it } - override fun StructureND.div(arg: Double): DoubleTensor { - val resBuffer = DoubleArray(asDoubleTensor().numElements) { i -> - asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] / arg - } - return DoubleTensor(shape, resBuffer) - } + override fun StructureND.div(arg: Double): DoubleTensor = map { it / arg } - override fun StructureND.div(arg: StructureND): DoubleTensor { - checkShapesCompatible(asDoubleTensor(), arg) - val resBuffer = DoubleArray(asDoubleTensor().numElements) { i -> - asDoubleTensor().mutableBuffer.array()[arg.asDoubleTensor().bufferStart + i] / - arg.asDoubleTensor().mutableBuffer.array()[arg.asDoubleTensor().bufferStart + i] - } - return DoubleTensor(asDoubleTensor().shape, resBuffer) - } + override fun StructureND.div(arg: StructureND): DoubleTensor = zip(this, arg) { l, r -> l / r } override fun Tensor.divAssign(value: Double) { - for (i in 0 until asDoubleTensor().numElements) { - asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] /= value - } + mapInPlace { it / value } } override fun Tensor.divAssign(arg: StructureND) { checkShapesCompatible(asDoubleTensor(), arg) - for (i in 0 until asDoubleTensor().numElements) { - asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] /= - arg.asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i] - } + mapIndexedInPlace { index, value -> value / arg[index] } } - override fun StructureND.unaryMinus(): DoubleTensor { - val resBuffer = DoubleArray(asDoubleTensor().numElements) { i -> - asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + i].unaryMinus() - } - return DoubleTensor(asDoubleTensor().shape, resBuffer) - } + override fun StructureND.unaryMinus(): DoubleTensor = map { -it } - override fun Tensor.transpose(i: Int, j: Int): DoubleTensor { - val ii = asDoubleTensor().minusIndex(i) - val jj = asDoubleTensor().minusIndex(j) - checkTranspose(asDoubleTensor().dimension, ii, jj) - val n = asDoubleTensor().numElements + override fun Tensor.transposed(i: Int, j: Int): DoubleTensor { + // TODO change strides instead of changing content + val dt = asDoubleTensor() + val ii = dt.minusIndex(i) + val jj = dt.minusIndex(j) + checkTranspose(dt.dimension, ii, jj) + val n = dt.linearSize val resBuffer = DoubleArray(n) - val resShape = asDoubleTensor().shape.copyOf() + val resShape = dt.shape.copyOf() resShape[ii] = resShape[jj].also { resShape[jj] = resShape[ii] } - val resTensor = DoubleTensor(resShape, resBuffer) + val resTensor = DoubleTensor(resShape, resBuffer.asBuffer()) for (offset in 0 until n) { - val oldMultiIndex = asDoubleTensor().indices.index(offset) + val oldMultiIndex = dt.indices.index(offset) val newMultiIndex = oldMultiIndex.copyOf() newMultiIndex[ii] = newMultiIndex[jj].also { newMultiIndex[jj] = newMultiIndex[ii] } val linearIndex = resTensor.indices.offset(newMultiIndex) - resTensor.mutableBuffer.array()[linearIndex] = - asDoubleTensor().mutableBuffer.array()[asDoubleTensor().bufferStart + offset] + resTensor.source[linearIndex] = dt.source[offset] } return resTensor } override fun Tensor.view(shape: IntArray): DoubleTensor { checkView(asDoubleTensor(), shape) - return DoubleTensor(shape, asDoubleTensor().mutableBuffer.array(), asDoubleTensor().bufferStart) + return DoubleTensor(shape, asDoubleTensor().source) } override fun Tensor.viewAs(other: StructureND): DoubleTensor = - asDoubleTensor().view(other.shape) + view(other.shape) /** * Broadcasting Matrix product of two tensors. @@ -417,28 +334,28 @@ public open class DoubleTensorAlgebra : */ @UnstableKMathAPI public infix fun StructureND.matmul(other: StructureND): DoubleTensor { - if (asDoubleTensor().shape.size == 1 && other.shape.size == 1) { - return DoubleTensor( - intArrayOf(1), - doubleArrayOf(asDoubleTensor().times(other).asDoubleTensor().mutableBuffer.array().sum()) - ) + if (shape.size == 1 && other.shape.size == 1) { + return DoubleTensor(intArrayOf(1), DoubleBuffer(times(other).sum())) } - var newThis = asDoubleTensor().copy() - var newOther = other.copy() - var penultimateDim = false var lastDim = false - if (asDoubleTensor().shape.size == 1) { + + //TODO do we need protective copy here? + var newThis: DoubleTensor = copyToTensor() + var newOther: DoubleTensor = other.copyToTensor() + + if (shape.size == 1) { penultimateDim = true - newThis = asDoubleTensor().view(intArrayOf(1) + asDoubleTensor().shape) - } - if (other.shape.size == 1) { - lastDim = true - newOther = other.asDoubleTensor().view(other.shape + intArrayOf(1)) + newThis = newThis.view(intArrayOf(1) + shape) } - val broadcastTensors = broadcastOuterTensors(newThis.asDoubleTensor(), newOther.asDoubleTensor()) + if (other.shape.size == 1) { + lastDim = true + newOther = newOther.view(other.shape + intArrayOf(1)) + } + + val broadcastTensors = broadcastOuterTensors(newThis, newOther) newThis = broadcastTensors[0] newOther = broadcastTensors[1] @@ -452,12 +369,20 @@ public open class DoubleTensorAlgebra : val resShape = newThis.shape.sliceArray(0..(newThis.shape.size - 2)) + intArrayOf(newOther.shape.last()) val resSize = resShape.reduce { acc, i -> acc * i } - val resTensor = DoubleTensor(resShape, DoubleArray(resSize)) + val resTensor = DoubleTensor(resShape, DoubleArray(resSize).asBuffer()) - for ((res, ab) in resTensor.matrixSequence().zip(newThis.matrixSequence().zip(newOther.matrixSequence()))) { - val (a, b) = ab - dotTo(a, b, res, l, m1, n) + val resMatrices = resTensor.matrices + val newThisMatrices = newThis.matrices + val newOtherMatrices = newOther.matrices + + for (i in resMatrices.indices) { + dotTo(newThisMatrices[i], newOtherMatrices[i], resMatrices[i], l, m1, n) } +// +// for ((res, ab) in resTensor.matrixSequence().zip(newThis.matrixSequence().zip(newOther.matrixSequence()))) { +// val (a, b) = ab +// dotTo(a, b, res, l, m1, n) +// } return if (penultimateDim) { resTensor.view(resTensor.shape.dropLast(2).toIntArray() + intArrayOf(resTensor.shape.last())) @@ -503,10 +428,10 @@ public open class DoubleTensorAlgebra : diagonalEntries.shape.slice(lessDim until greaterDim - 1).toIntArray() + intArrayOf(diagonalEntries.shape[n - 1] + abs(realOffset)) + diagonalEntries.shape.slice(greaterDim - 1 until n - 1).toIntArray() - val resTensor = zeros(resShape) + val resTensor: DoubleTensor = zeros(resShape) - for (i in 0 until diagonalEntries.asDoubleTensor().numElements) { - val multiIndex = diagonalEntries.asDoubleTensor().indices.index(i) + for (i in 0 until diagonalEntries.indices.linearSize) { + val multiIndex = diagonalEntries.indices.index(i) var offset1 = 0 var offset2 = abs(realOffset) @@ -522,7 +447,7 @@ public open class DoubleTensorAlgebra : resTensor[diagonalMultiIndex] = diagonalEntries[multiIndex] } - return resTensor.asDoubleTensor() + return resTensor } /** @@ -542,23 +467,20 @@ public open class DoubleTensorAlgebra : * @param other the tensor to compare with `input` tensor. * @return true if two tensors have the same shape and elements, false otherwise. */ - public infix fun Tensor.eq(other: Tensor): Boolean = asDoubleTensor().eq(other, 1e-5) + public infix fun Tensor.eq(other: Tensor): Boolean = eq(other, 1e-5) private fun Tensor.eq( other: Tensor, eqFunction: (Double, Double) -> Boolean, ): Boolean { + //TODO optimize tensor conversion checkShapesCompatible(asDoubleTensor(), other) - val n = asDoubleTensor().numElements - if (n != other.asDoubleTensor().numElements) { + val n = asDoubleTensor().linearSize + if (n != other.asDoubleTensor().linearSize) { return false } for (i in 0 until n) { - if (!eqFunction( - asDoubleTensor().mutableBuffer[asDoubleTensor().bufferStart + i], - other.asDoubleTensor().mutableBuffer[other.asDoubleTensor().bufferStart + i] - ) - ) { + if (!eqFunction(asDoubleTensor().source[i], other.asDoubleTensor().source[i])) { return false } } @@ -586,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(asDoubleTensor().shape, getRandomNormals(asDoubleTensor().shape.reduce(Int::times), seed)) + DoubleTensor(shape, getRandomNormals(shape.reduce(Int::times), seed)) /** * Concatenates a sequence of tensors with equal shapes along the first dimension. @@ -599,11 +521,12 @@ public open class DoubleTensorAlgebra : val shape = tensors[0].shape check(tensors.all { it.shape contentEquals shape }) { "Tensors must have same shapes" } val resShape = intArrayOf(tensors.size) + shape - val resBuffer = tensors.flatMap { - it.asDoubleTensor().mutableBuffer.array().drop(it.asDoubleTensor().bufferStart) - .take(it.asDoubleTensor().numElements) - }.toDoubleArray() - return DoubleTensor(resShape, resBuffer, 0) +// val resBuffer: List = tensors.flatMap { +// it.asDoubleTensor().source.array.drop(it.asDoubleTensor().bufferStart) +// .take(it.asDoubleTensor().linearSize) +// } + val resBuffer = tensors.map { it.asDoubleTensor().source }.concat() + return DoubleTensor(resShape, resBuffer) } /** @@ -614,14 +537,12 @@ public open class DoubleTensorAlgebra : */ public fun Tensor.rowsByIndices(indices: IntArray): DoubleTensor = stack(indices.map { getTensor(it) }) - private inline fun StructureND.fold(foldFunction: (DoubleArray) -> Double): Double = - foldFunction(asDoubleTensor().copyArray()) - private inline fun StructureND.foldDim( + private inline fun StructureND.foldDimToDouble( dim: Int, keepDim: Boolean, - foldFunction: (DoubleArray) -> R, - ): BufferedTensor { + foldFunction: (DoubleArray) -> Double, + ): DoubleTensor { check(dim < dimension) { "Dimension $dim out of range $dimension" } val resShape = if (keepDim) { shape.take(dim).toIntArray() + intArrayOf(1) + shape.takeLast(dimension - dim - 1).toIntArray() @@ -630,9 +551,37 @@ public open class DoubleTensorAlgebra : } val resNumElements = resShape.reduce(Int::times) val init = foldFunction(DoubleArray(1) { 0.0 }) - val resTensor = BufferedTensor( + val resTensor = DoubleTensor( resShape, - MutableBuffer.auto(resNumElements) { init }, 0 + DoubleBuffer(resNumElements) { init } + ) + val dt = asDoubleTensor() + for (index in resTensor.indices) { + val prefix = index.take(dim).toIntArray() + val suffix = index.takeLast(dimension - dim - 1).toIntArray() + resTensor[index] = foldFunction(DoubleArray(shape[dim]) { i -> + dt[prefix + intArrayOf(i) + suffix] + }) + } + return resTensor + } + + private inline fun StructureND.foldDimToInt( + dim: Int, + keepDim: Boolean, + foldFunction: (DoubleArray) -> Int, + ): IntTensor { + check(dim < dimension) { "Dimension $dim out of range $dimension" } + val resShape = if (keepDim) { + shape.take(dim).toIntArray() + intArrayOf(1) + shape.takeLast(dimension - dim - 1).toIntArray() + } else { + shape.take(dim).toIntArray() + shape.takeLast(dimension - dim - 1).toIntArray() + } + val resNumElements = resShape.reduce(Int::times) + val init = foldFunction(DoubleArray(1) { 0.0 }) + val resTensor = IntTensor( + resShape, + IntBuffer(resNumElements) { init } ) for (index in resTensor.indices) { val prefix = index.take(dim).toIntArray() @@ -644,68 +593,71 @@ public open class DoubleTensorAlgebra : return resTensor } - override fun StructureND.sum(): Double = asDoubleTensor().fold { it.sum() } + + override fun StructureND.sum(): Double = reduceElements { it.array.sum() } override fun StructureND.sum(dim: Int, keepDim: Boolean): DoubleTensor = - foldDim(dim, keepDim) { x -> x.sum() }.asDoubleTensor() + foldDimToDouble(dim, keepDim) { x -> x.sum() } - override fun StructureND.min(): Double = this.fold { it.minOrNull()!! } + override fun StructureND.min(): Double = reduceElements { it.array.min() } override fun StructureND.min(dim: Int, keepDim: Boolean): DoubleTensor = - foldDim(dim, keepDim) { x -> x.minOrNull()!! }.asDoubleTensor() + foldDimToDouble(dim, keepDim) { x -> x.minOrNull()!! } - override fun StructureND.argMin(dim: Int, keepDim: Boolean): Tensor = foldDim(dim, keepDim) { x -> - x.withIndex().minByOrNull { it.value }?.index!! - }.asIntTensor() + override fun StructureND.argMin(dim: Int, keepDim: Boolean): Tensor = foldDimToInt(dim, keepDim) { x -> + x.withIndex().minBy { it.value }.index + } - override fun StructureND.max(): Double = this.fold { it.maxOrNull()!! } + override fun StructureND.max(): Double = reduceElements { it.array.max() } override fun StructureND.max(dim: Int, keepDim: Boolean): DoubleTensor = - foldDim(dim, keepDim) { x -> x.maxOrNull()!! }.asDoubleTensor() + foldDimToDouble(dim, keepDim) { x -> x.maxOrNull()!! } override fun StructureND.argMax(dim: Int, keepDim: Boolean): IntTensor = - foldDim(dim, keepDim) { x -> - x.withIndex().maxByOrNull { it.value }?.index!! - }.asIntTensor() + foldDimToInt(dim, keepDim) { x -> + x.withIndex().maxBy { it.value }.index + } - override fun StructureND.mean(): Double = this.fold { it.sum() / asDoubleTensor().numElements } + override fun StructureND.mean(): Double = sum() / indices.linearSize - override fun StructureND.mean(dim: Int, keepDim: Boolean): DoubleTensor = foldDim(dim, keepDim) { arr -> - check(dim < dimension) { "Dimension $dim out of range $dimension" } - arr.sum() / shape[dim] - }.asDoubleTensor() + override fun StructureND.mean(dim: Int, keepDim: Boolean): DoubleTensor = + foldDimToDouble(dim, keepDim) { arr -> + check(dim < dimension) { "Dimension $dim out of range $dimension" } + arr.sum() / shape[dim] + } - override fun StructureND.std(): Double = fold { arr -> - val mean = arr.sum() / asDoubleTensor().numElements - sqrt(arr.sumOf { (it - mean) * (it - mean) } / (asDoubleTensor().numElements - 1)) + override fun StructureND.std(): Double = reduceElements { arr -> + val mean = arr.array.sum() / indices.linearSize + sqrt(arr.array.sumOf { (it - mean) * (it - mean) } / (indices.linearSize - 1)) } - override fun StructureND.std(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( + override fun StructureND.std(dim: Int, keepDim: Boolean): DoubleTensor = foldDimToDouble( dim, keepDim ) { arr -> check(dim < dimension) { "Dimension $dim out of range $dimension" } val mean = arr.sum() / shape[dim] sqrt(arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1)) - }.asDoubleTensor() - - override fun StructureND.variance(): Double = fold { arr -> - val mean = arr.sum() / asDoubleTensor().numElements - arr.sumOf { (it - mean) * (it - mean) } / (asDoubleTensor().numElements - 1) } - override fun StructureND.variance(dim: Int, keepDim: Boolean): DoubleTensor = foldDim( + override fun StructureND.variance(): Double = reduceElements { arr -> + val linearSize = indices.linearSize + val mean = arr.array.sum() / linearSize + arr.array.sumOf { (it - mean) * (it - mean) } / (linearSize - 1) + } + + override fun StructureND.variance(dim: Int, keepDim: Boolean): DoubleTensor = foldDimToDouble( dim, keepDim ) { arr -> check(dim < dimension) { "Dimension $dim out of range $dimension" } val mean = arr.sum() / shape[dim] arr.sumOf { (it - mean) * (it - mean) } / (shape[dim] - 1) - }.asDoubleTensor() + } - private fun cov(x: DoubleTensor, y: DoubleTensor): Double { + private fun cov(x: StructureND, y: StructureND): Double { val n = x.shape[0] return ((x - x.mean()) * (y - y.mean())).mean() * n / (n - 1) } @@ -725,45 +677,45 @@ public open class DoubleTensorAlgebra : check(tensors.all { it.shape contentEquals intArrayOf(m) }) { "Tensors must have same shapes" } val resTensor = DoubleTensor( intArrayOf(n, n), - DoubleArray(n * n) { 0.0 } + DoubleBuffer(n * n) { 0.0 } ) for (i in 0 until n) { for (j in 0 until n) { - resTensor[intArrayOf(i, j)] = cov(tensors[i].asDoubleTensor(), tensors[j].asDoubleTensor()) + resTensor[intArrayOf(i, j)] = cov(tensors[i], tensors[j]) } } return resTensor } - override fun StructureND.exp(): DoubleTensor = asDoubleTensor().map { exp(it) } + override fun StructureND.exp(): DoubleTensor = map { exp(it) } - override fun StructureND.ln(): DoubleTensor = asDoubleTensor().map { ln(it) } + override fun StructureND.ln(): DoubleTensor = map { ln(it) } - override fun StructureND.sqrt(): DoubleTensor = asDoubleTensor().map { sqrt(it) } + override fun StructureND.sqrt(): DoubleTensor = map { sqrt(it) } - override fun StructureND.cos(): DoubleTensor = asDoubleTensor().map { cos(it) } + override fun StructureND.cos(): DoubleTensor = map { cos(it) } - override fun StructureND.acos(): DoubleTensor = asDoubleTensor().map { acos(it) } + override fun StructureND.acos(): DoubleTensor = map { acos(it) } - override fun StructureND.cosh(): DoubleTensor = asDoubleTensor().map { cosh(it) } + override fun StructureND.cosh(): DoubleTensor = map { cosh(it) } - override fun StructureND.acosh(): DoubleTensor = asDoubleTensor().map { acosh(it) } + override fun StructureND.acosh(): DoubleTensor = map { acosh(it) } - override fun StructureND.sin(): DoubleTensor = asDoubleTensor().map { sin(it) } + override fun StructureND.sin(): DoubleTensor = map { sin(it) } - override fun StructureND.asin(): DoubleTensor = asDoubleTensor().map { asin(it) } + override fun StructureND.asin(): DoubleTensor = map { asin(it) } - override fun StructureND.sinh(): DoubleTensor = asDoubleTensor().map { sinh(it) } + override fun StructureND.sinh(): DoubleTensor = map { sinh(it) } - override fun StructureND.asinh(): DoubleTensor = asDoubleTensor().map { asinh(it) } + override fun StructureND.asinh(): DoubleTensor = map { asinh(it) } - override fun StructureND.tan(): DoubleTensor = asDoubleTensor().map { tan(it) } + override fun StructureND.tan(): DoubleTensor = map { tan(it) } - override fun StructureND.atan(): DoubleTensor = asDoubleTensor().map { atan(it) } + override fun StructureND.atan(): DoubleTensor = map { atan(it) } - override fun StructureND.tanh(): DoubleTensor = asDoubleTensor().map { tanh(it) } + override fun StructureND.tanh(): DoubleTensor = map { tanh(it) } - override fun StructureND.atanh(): DoubleTensor = asDoubleTensor().map { atanh(it) } + override fun StructureND.atanh(): DoubleTensor = map { atanh(it) } override fun power(arg: StructureND, pow: Number): StructureND = if (pow is Int) { arg.map { it.pow(pow) } @@ -771,9 +723,9 @@ public open class DoubleTensorAlgebra : arg.map { it.pow(pow.toDouble()) } } - override fun StructureND.ceil(): DoubleTensor = asDoubleTensor().map { ceil(it) } + override fun StructureND.ceil(): DoubleTensor = map { ceil(it) } - override fun StructureND.floor(): DoubleTensor = asDoubleTensor().map { floor(it) } + override fun StructureND.floor(): DoubleTensor = map { floor(it) } override fun StructureND.inv(): DoubleTensor = invLU(1e-9) @@ -789,7 +741,7 @@ public open class DoubleTensorAlgebra : * The `pivots` has the shape ``(∗, min(m, n))``. `pivots` stores all the intermediate transpositions of rows. */ public fun StructureND.luFactor(epsilon: Double): Pair = - computeLU(asDoubleTensor(), epsilon) + computeLU(this, epsilon) ?: throw IllegalArgumentException("Tensor contains matrices which are singular at precision $epsilon") /** @@ -825,14 +777,14 @@ public open class DoubleTensorAlgebra : ) { "Inappropriate shapes of input tensors" } val n = luTensor.shape.last() - val pTensor = luTensor.zeroesLike() + val pTensor = zeroesLike(luTensor) pTensor .matrixSequence() .zip(pivotsTensor.asIntTensor().vectorSequence()) .forEach { (p, pivot) -> pivInit(p.as2D(), pivot.as1D(), n) } - val lTensor = luTensor.zeroesLike() - val uTensor = luTensor.zeroesLike() + val lTensor = zeroesLike(luTensor) + val uTensor = zeroesLike(luTensor) lTensor.matrixSequence() .zip(uTensor.matrixSequence()) @@ -863,7 +815,7 @@ public open class DoubleTensorAlgebra : checkPositiveDefinite(asDoubleTensor(), epsilon) val n = shape.last() - val lTensor = zeroesLike() + 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) @@ -875,15 +827,17 @@ public open class DoubleTensorAlgebra : override fun StructureND.qr(): Pair { checkSquareMatrix(shape) - val qTensor = zeroesLike() - val rTensor = zeroesLike() + val qTensor = zeroesLike(this) + val rTensor = zeroesLike(this) + + //TODO replace with cycle asDoubleTensor().matrixSequence() .zip( (qTensor.matrixSequence() .zip(rTensor.matrixSequence())) ).forEach { (matrix, qr) -> val (q, r) = qr - qrHelper(matrix.toTensor(), q.toTensor(), r.as2D()) + qrHelper(matrix, q, r.as2D()) } return qTensor to rTensor @@ -906,14 +860,14 @@ public open class DoubleTensorAlgebra : * @return a triple `Triple(U, S, V)`. */ public fun StructureND.svd(epsilon: Double): Triple { - val size = asDoubleTensor().dimension - val commonShape = asDoubleTensor().shape.sliceArray(0 until size - 2) - val (n, m) = asDoubleTensor().shape.sliceArray(size - 2 until size) + val size = dimension + val commonShape = shape.sliceArray(0 until size - 2) + val (n, m) = shape.sliceArray(size - 2 until size) val uTensor = zeros(commonShape + intArrayOf(min(n, m), n)) val sTensor = zeros(commonShape + intArrayOf(min(n, m))) val vTensor = zeros(commonShape + intArrayOf(min(n, m), m)) - val matrices = asDoubleTensor().matrices + val matrices: VirtualBuffer = asDoubleTensor().matrices val uTensors = uTensor.matrices val sTensorVectors = sTensor.vectors val vTensors = vTensor.matrices @@ -928,14 +882,12 @@ public open class DoubleTensorAlgebra : val matrixSize = matrix.shape.reduce { acc, i -> acc * i } val curMatrix = DoubleTensor( matrix.shape, - matrix.mutableBuffer.array() - .slice(matrix.bufferStart until matrix.bufferStart + matrixSize) - .toDoubleArray() + matrix.source.view(0, matrixSize) ) svdHelper(curMatrix, usv, m, n, epsilon) } - return Triple(uTensor.transpose(), sTensor, vTensor.transpose()) + return Triple(uTensor.transposed(), sTensor, vTensor.transposed()) } override fun StructureND.symEig(): Pair = @@ -950,6 +902,7 @@ public open class DoubleTensorAlgebra : * @return a pair `eigenvalues to eigenvectors`. */ public fun StructureND.symEigSvd(epsilon: Double): Pair { + //TODO optimize conversion checkSymmetric(asDoubleTensor(), epsilon) fun MutableStructure2D.cleanSym(n: Int) { @@ -964,9 +917,9 @@ public open class DoubleTensorAlgebra : } } - val (u, s, v) = asDoubleTensor().svd(epsilon) + val (u, s, v) = svd(epsilon) val shp = s.shape + intArrayOf(1) - val utv = u.transpose() matmul v + val utv = u.transposed() matmul v val n = s.shape.last() for (matrix in utv.matrixSequence()) { matrix.as2D().cleanSym(n) @@ -977,6 +930,7 @@ public open class DoubleTensorAlgebra : } public fun StructureND.symEigJacobi(maxIteration: Int, epsilon: Double): Pair { + //TODO optimize conversion checkSymmetric(asDoubleTensor(), epsilon) val size = this.dimension @@ -991,12 +945,12 @@ public open class DoubleTensorAlgebra : for (i in 0 until matrix2D.rowNum) { for (j in 0 until matrix2D.colNum) { - eigenvectors.mutableBuffer.array()[eigenvectorStart + i * matrix2D.rowNum + j] = v[i, j] + eigenvectors.source[eigenvectorStart + i * matrix2D.rowNum + j] = v[i, j] } } for (i in 0 until matrix2D.rowNum) { - eigenvalues.mutableBuffer.array()[eigenvalueStart + i] = d[i] + eigenvalues.source[eigenvalueStart + i] = d[i] } eigenvalueStart += this.shape.last() @@ -1006,121 +960,6 @@ public open class DoubleTensorAlgebra : return eigenvalues to eigenvectors } - private fun MutableStructure2D.jacobiHelper( - maxIteration: Int, - epsilon: Double, - ): Pair, Structure2D> { - val n = this.shape[0] - val A_ = this.copy() - val V = eye(n) - val D = DoubleTensor(intArrayOf(n), (0 until this.rowNum).map { this[it, it] }.toDoubleArray()).as1D() - val B = DoubleTensor(intArrayOf(n), (0 until this.rowNum).map { this[it, it] }.toDoubleArray()).as1D() - val Z = zeros(intArrayOf(n)).as1D() - - // assume that buffered tensor is square matrix - operator fun BufferedTensor.get(i: Int, j: Int): Double { - return this.mutableBuffer.array()[bufferStart + i * this.shape[0] + j] - } - - operator fun BufferedTensor.set(i: Int, j: Int, value: Double) { - this.mutableBuffer.array()[bufferStart + i * this.shape[0] + j] = value - } - - fun maxOffDiagonal(matrix: BufferedTensor): Double { - var maxOffDiagonalElement = 0.0 - for (i in 0 until n - 1) { - for (j in i + 1 until n) { - maxOffDiagonalElement = max(maxOffDiagonalElement, abs(matrix[i, j])) - } - } - return maxOffDiagonalElement - } - - fun rotate(a: BufferedTensor, s: Double, tau: Double, i: Int, j: Int, k: Int, l: Int) { - val g = a[i, j] - val h = a[k, l] - a[i, j] = g - s * (h + g * tau) - a[k, l] = h + s * (g - h * tau) - } - - fun jacobiIteration( - a: BufferedTensor, - v: BufferedTensor, - d: MutableStructure1D, - z: MutableStructure1D, - ) { - for (ip in 0 until n - 1) { - for (iq in ip + 1 until n) { - val g = 100.0 * abs(a[ip, iq]) - - if (g <= epsilon * abs(d[ip]) && g <= epsilon * abs(d[iq])) { - a[ip, iq] = 0.0 - continue - } - - var h = d[iq] - d[ip] - val t = when { - g <= epsilon * abs(h) -> (a[ip, iq]) / h - else -> { - val theta = 0.5 * h / (a[ip, iq]) - val denominator = abs(theta) + sqrt(1.0 + theta * theta) - if (theta < 0.0) -1.0 / denominator else 1.0 / denominator - } - } - - val c = 1.0 / sqrt(1 + t * t) - val s = t * c - val tau = s / (1.0 + c) - h = t * a[ip, iq] - z[ip] -= h - z[iq] += h - d[ip] -= h - d[iq] += h - a[ip, iq] = 0.0 - - for (j in 0 until ip) { - rotate(a, s, tau, j, ip, j, iq) - } - for (j in (ip + 1) until iq) { - rotate(a, s, tau, ip, j, j, iq) - } - for (j in (iq + 1) until n) { - rotate(a, s, tau, ip, j, iq, j) - } - for (j in 0 until n) { - rotate(v, s, tau, j, ip, j, iq) - } - } - } - } - - fun updateDiagonal( - d: MutableStructure1D, - z: MutableStructure1D, - b: MutableStructure1D, - ) { - for (ip in 0 until d.size) { - b[ip] += z[ip] - d[ip] = b[ip] - z[ip] = 0.0 - } - } - - var sm = maxOffDiagonal(A_) - for (iteration in 0 until maxIteration) { - if (sm < epsilon) { - break - } - - jacobiIteration(A_, V, D, Z) - updateDiagonal(D, Z, B) - sm = maxOffDiagonal(A_) - } - - // TODO sort eigenvalues - return D to V.as2D() - } - /** * Computes the determinant of a square matrix input, or of each square matrix in a batched input * using LU factorization algorithm. @@ -1130,15 +969,16 @@ public open class DoubleTensorAlgebra : * @return the determinant. */ public fun StructureND.detLU(epsilon: Double = 1e-9): DoubleTensor { - checkSquareMatrix(asDoubleTensor().shape) - val luTensor = asDoubleTensor().copy() - val pivotsTensor = asDoubleTensor().setUpPivots() + checkSquareMatrix(shape) + //TODO check for unnecessary copies + val luTensor = copyToTensor() + val pivotsTensor = setUpPivots() val n = shape.size val detTensorShape = IntArray(n - 1) { i -> shape[i] } detTensorShape[n - 2] = 1 - val resBuffer = DoubleArray(detTensorShape.reduce(Int::times)) { 0.0 } + val resBuffer = DoubleBuffer(detTensorShape.reduce(Int::times)) { 0.0 } val detTensor = DoubleTensor( detTensorShape, @@ -1164,8 +1004,9 @@ public open class DoubleTensorAlgebra : */ public fun StructureND.invLU(epsilon: Double = 1e-9): DoubleTensor { val (luTensor, pivotsTensor) = luFactor(epsilon) - val invTensor = luTensor.zeroesLike() + val invTensor = zeroesLike(luTensor) + //TODO replace sequence with a cycle val seq = luTensor.matrixSequence().zip(pivotsTensor.vectorSequence()).zip(invTensor.matrixSequence()) for ((luP, invMatrix) in seq) { val (lu, pivots) = luP @@ -1188,7 +1029,7 @@ public open class DoubleTensorAlgebra : * @return triple of `P`, `L` and `U` tensors. */ public fun StructureND.lu(epsilon: Double = 1e-9): Triple { - val (lu, pivots) = asDoubleTensor().luFactor(epsilon) + val (lu, pivots) = luFactor(epsilon) return luPivot(lu, pivots) } 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 a2b942bf0..ed96b6c8f 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensor.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensor.kt @@ -5,17 +5,87 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.structures.IntBuffer -import space.kscience.kmath.tensors.core.internal.array +import space.kscience.kmath.structures.* /** * Default [BufferedTensor] implementation for [Int] values */ -public class IntTensor @PublishedApi internal constructor( - shape: IntArray, - buffer: IntArray, - offset: Int = 0, -) : BufferedTensor(shape, IntBuffer(buffer), offset) { - public fun asDouble(): DoubleTensor = - DoubleTensor(shape, mutableBuffer.array().map { it.toDouble() }.toDoubleArray(), bufferStart) +public class OffsetIntBuffer( + private val source: IntBuffer, + private val offset: Int, + override val size: Int, +) : MutableBuffer { + + init { + require(offset >= 0) { "Offset must be non-negative" } + require(size >= 0) { "Size must be non-negative" } + require(offset + size <= source.size) { "Maximum index must be inside source dimension" } + } + + override fun set(index: Int, value: Int) { + require(index in 0 until size) { "Index must be in [0, size)" } + source[index + offset] = value + } + + override fun get(index: Int): Int = source[index + offset] + + /** + * Copy only a part of buffer that belongs to this tensor + */ + override fun copy(): IntBuffer = source.array.copyOfRange(offset, offset + size).asBuffer() + + override fun iterator(): Iterator = iterator { + for (i in indices) { + yield(get(i)) + } + } + + override fun toString(): String = Buffer.toString(this) + + public fun view(addOffset: Int, newSize: Int = size - addOffset): OffsetIntBuffer = + OffsetIntBuffer(source, offset + addOffset, newSize) +} + +public fun OffsetIntBuffer.slice(range: IntRange): OffsetIntBuffer = view(range.first, range.last - range.first) + +/** + * Map only operable content of the offset buffer + */ +public inline fun OffsetIntBuffer.map(operation: (Int) -> Int): IntBuffer = + IntBuffer(size) { operation(get(it)) } + +public inline fun OffsetIntBuffer.zip( + other: OffsetIntBuffer, + operation: (l: Int, r: Int) -> Int, +): IntBuffer { + require(size == other.size) { "The sizes of zipped buffers must be the same" } + return IntBuffer(size) { operation(get(it), other[it]) } +} + +/** + * map in place + */ +public inline fun OffsetIntBuffer.mapInPlace(operation: (Int) -> Int) { + indices.forEach { set(it, operation(get(it))) } +} + +/** + * Default [BufferedTensor] implementation for [Int] values + */ +public class IntTensor( + shape: IntArray, + override val source: OffsetIntBuffer, +) : BufferedTensor(shape) { + + init { + require(linearSize == source.size) { "Source buffer size must be equal tensor size" } + } + + public constructor(shape: IntArray, buffer: IntBuffer) : this(shape, OffsetIntBuffer(buffer, 0, buffer.size)) + + override fun get(index: IntArray): Int = this.source[indices.offset(index)] + + override fun set(index: IntArray, value: Int) { + source[indices.offset(index)] = value + } } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensorAlgebra.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/IntTensorAlgebra.kt index 3ddbd3301..7c18fe533 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 @@ -11,7 +11,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.* import space.kscience.kmath.operations.IntRing -import space.kscience.kmath.structures.MutableBuffer +import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.api.* import space.kscience.kmath.tensors.core.internal.* import kotlin.math.* @@ -23,10 +23,6 @@ public open class IntTensorAlgebra : TensorAlgebra { public companion object : IntTensorAlgebra() - override fun StructureND.dot(other: StructureND): Tensor { - TODO("Not yet implemented") - } - override val elementAlgebra: IntRing get() = IntRing @@ -36,56 +32,64 @@ public open class IntTensorAlgebra : TensorAlgebra { * @param transform the function to be applied to each element of the tensor. * @return the resulting tensor after applying the function. */ - @PerformancePitfall @Suppress("OVERRIDE_BY_INLINE") final override inline fun StructureND.map(transform: IntRing.(Int) -> Int): IntTensor { val tensor = this.asIntTensor() //TODO remove additional copy - val sourceArray = tensor.copyArray() - val array = IntArray(tensor.numElements) { IntRing.transform(sourceArray[it]) } + val array = IntBuffer(tensor.source.size) { IntRing.transform(tensor.source[it]) } return IntTensor( tensor.shape, array, - tensor.bufferStart ) } - @PerformancePitfall + public inline fun Tensor.mapInPlace(operation: (Int) -> Int) { + if (this is IntTensor) { + source.mapInPlace(operation) + } else { + indices.forEach { set(it, operation(get(it))) } + } + } + + public inline fun Tensor.mapIndexedInPlace(operation: (IntArray, Int) -> Int) { + indices.forEach { set(it, operation(it, get(it))) } + } + @Suppress("OVERRIDE_BY_INLINE") final override inline fun StructureND.mapIndexed(transform: IntRing.(index: IntArray, Int) -> Int): IntTensor { val tensor = this.asIntTensor() //TODO remove additional copy - val sourceArray = tensor.copyArray() - val array = IntArray(tensor.numElements) { IntRing.transform(tensor.indices.index(it), sourceArray[it]) } - return IntTensor( - tensor.shape, - array, - tensor.bufferStart - ) + val buffer = IntBuffer(tensor.source.size) { + IntRing.transform(tensor.indices.index(it), tensor.source[it]) + } + return IntTensor(tensor.shape, buffer) } - @PerformancePitfall - override fun zip( + @Suppress("OVERRIDE_BY_INLINE") + final override inline fun zip( left: StructureND, right: StructureND, transform: IntRing.(Int, Int) -> Int, ): IntTensor { - require(left.shape.contentEquals(right.shape)) { - "The shapes in zip are not equal: left - ${left.shape}, right - ${right.shape}" - } + checkShapesCompatible(left, right) + val leftTensor = left.asIntTensor() - val leftArray = leftTensor.copyArray() val rightTensor = right.asIntTensor() - val rightArray = rightTensor.copyArray() - val array = IntArray(leftTensor.numElements) { IntRing.transform(leftArray[it], rightArray[it]) } - return IntTensor( - leftTensor.shape, - array - ) + val buffer = IntBuffer(leftTensor.source.size) { + IntRing.transform(leftTensor.source[it], rightTensor.source[it]) + } + return IntTensor(leftTensor.shape, buffer) } - override fun StructureND.valueOrNull(): Int? = if (asIntTensor().shape contentEquals intArrayOf(1)) - asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart] else null + + public inline fun StructureND.reduceElements(transform: (IntBuffer) -> Int): Int = + transform(asIntTensor().source.copy()) + //TODO do we need protective copy? + + override fun StructureND.valueOrNull(): Int? { + val dt = asIntTensor() + return if (dt.shape contentEquals intArrayOf(1)) dt.source[0] else null + } override fun StructureND.value(): Int = valueOrNull() ?: throw IllegalArgumentException("The tensor shape is $shape, but value method is allowed only for shape [1]") @@ -94,16 +98,16 @@ public open class IntTensorAlgebra : TensorAlgebra { * Constructs a tensor with the specified shape and data. * * @param shape the desired shape for the tensor. - * @param buffer one-dimensional data array. - * @return tensor with the [shape] shape and [buffer] data. + * @param array one-dimensional data array. + * @return tensor with the [shape] shape and [array] data. */ - public fun fromArray(shape: IntArray, buffer: IntArray): IntTensor { - checkEmptyShape(shape) - check(buffer.isNotEmpty()) { "Illegal empty buffer provided" } - check(buffer.size == shape.reduce(Int::times)) { - "Inconsistent shape ${shape.toList()} for buffer of size ${buffer.size} provided" + public fun fromArray(shape: IntArray, array: IntArray): IntTensor { + checkNotEmptyShape(shape) + check(array.isNotEmpty()) { "Illegal empty buffer provided" } + check(array.size == shape.reduce(Int::times)) { + "Inconsistent shape ${shape.toList()} for buffer of size ${array.size} provided" } - return IntTensor(shape, buffer, 0) + return IntTensor(shape, array.asBuffer()) } /** @@ -119,10 +123,10 @@ public open class IntTensorAlgebra : TensorAlgebra { ) override fun Tensor.getTensor(i: Int): IntTensor { - val lastShape = asIntTensor().shape.drop(1).toIntArray() + val dt = asIntTensor() + val lastShape = shape.drop(1).toIntArray() val newShape = if (lastShape.isNotEmpty()) lastShape else intArrayOf(1) - val newStart = newShape.reduce(Int::times) * i + asIntTensor().bufferStart - return IntTensor(newShape, asIntTensor().mutableBuffer.array(), newStart) + return IntTensor(newShape, dt.source.view(newShape.reduce(Int::times) * i)) } /** @@ -133,8 +137,8 @@ public open class IntTensorAlgebra : TensorAlgebra { * @return tensor with the [shape] shape and filled with [value]. */ public fun full(value: Int, shape: IntArray): IntTensor { - checkEmptyShape(shape) - val buffer = IntArray(shape.reduce(Int::times)) { value } + checkNotEmptyShape(shape) + val buffer = IntBuffer(shape.reduce(Int::times)) { value } return IntTensor(shape, buffer) } @@ -144,9 +148,9 @@ public open class IntTensorAlgebra : TensorAlgebra { * @param value the value to fill the output tensor with. * @return tensor with the `input` tensor shape and filled with [value]. */ - public fun Tensor.fullLike(value: Int): IntTensor { - val shape = asIntTensor().shape - val buffer = IntArray(asIntTensor().numElements) { value } + public fun fullLike(structureND: StructureND<*>, value: Int): IntTensor { + val shape = structureND.shape + val buffer = IntBuffer(structureND.indices.linearSize) { value } return IntTensor(shape, buffer) } @@ -163,7 +167,7 @@ public open class IntTensorAlgebra : TensorAlgebra { * * @return tensor filled with the scalar value `0`, with the same shape as `input` tensor. */ - public fun StructureND.zeroesLike(): IntTensor = asIntTensor().fullLike(0) + public fun zeroesLike(structureND: StructureND): IntTensor = fullLike(structureND.asIntTensor(), 0) /** * Returns a tensor filled with the scalar value `1`, with the shape defined by the variable argument [shape]. @@ -178,7 +182,7 @@ public open class IntTensorAlgebra : TensorAlgebra { * * @return tensor filled with the scalar value `1`, with the same shape as `input` tensor. */ - public fun Tensor.onesLike(): IntTensor = asIntTensor().fullLike(1) + public fun onesLike(structureND: Tensor<*>): IntTensor = fullLike(structureND, 1) /** * Returns a 2D tensor with shape ([n], [n]), with ones on the diagonal and zeros elsewhere. @@ -188,7 +192,7 @@ public open class IntTensorAlgebra : TensorAlgebra { */ public fun eye(n: Int): IntTensor { val shape = intArrayOf(n, n) - val buffer = IntArray(n * n) { 0 } + val buffer = IntBuffer(n * n) { 0 } val res = IntTensor(shape, buffer) for (i in 0 until n) { res[intArrayOf(i, i)] = 1 @@ -196,151 +200,92 @@ public open class IntTensorAlgebra : TensorAlgebra { return res } - /** - * Return a copy of the tensor. - * - * @return a copy of the `input` tensor with a copied buffer. - */ - public fun StructureND.copy(): IntTensor = - IntTensor(asIntTensor().shape, asIntTensor().mutableBuffer.array().copyOf(), asIntTensor().bufferStart) + override fun Int.plus(arg: StructureND): IntTensor = arg.map { this@plus + it } - override fun Int.plus(arg: StructureND): IntTensor { - val resBuffer = IntArray(arg.asIntTensor().numElements) { i -> - arg.asIntTensor().mutableBuffer.array()[arg.asIntTensor().bufferStart + i] + this - } - return IntTensor(arg.shape, resBuffer) - } + override fun StructureND.plus(arg: Int): IntTensor = map { it + arg } - override fun StructureND.plus(arg: Int): IntTensor = arg + asIntTensor() - - override fun StructureND.plus(arg: StructureND): IntTensor { - checkShapesCompatible(asIntTensor(), arg.asIntTensor()) - val resBuffer = IntArray(asIntTensor().numElements) { i -> - asIntTensor().mutableBuffer.array()[i] + arg.asIntTensor().mutableBuffer.array()[i] - } - return IntTensor(asIntTensor().shape, resBuffer) - } + override fun StructureND.plus(arg: StructureND): IntTensor = zip(this, arg) { l, r -> l + r } override fun Tensor.plusAssign(value: Int) { - for (i in 0 until asIntTensor().numElements) { - asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + i] += value - } + mapInPlace { it + value } } override fun Tensor.plusAssign(arg: StructureND) { checkShapesCompatible(asIntTensor(), arg.asIntTensor()) - for (i in 0 until asIntTensor().numElements) { - asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + i] += - arg.asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + i] + mapIndexedInPlace { index, value -> + value + arg[index] } } - override fun Int.minus(arg: StructureND): IntTensor { - val resBuffer = IntArray(arg.asIntTensor().numElements) { i -> - this - arg.asIntTensor().mutableBuffer.array()[arg.asIntTensor().bufferStart + i] - } - return IntTensor(arg.shape, resBuffer) - } + override fun Int.minus(arg: StructureND): IntTensor = arg.map { this@minus - it } - override fun StructureND.minus(arg: Int): IntTensor { - val resBuffer = IntArray(asIntTensor().numElements) { i -> - asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + i] - arg - } - return IntTensor(asIntTensor().shape, resBuffer) - } + override fun StructureND.minus(arg: Int): IntTensor = map { it - arg } - override fun StructureND.minus(arg: StructureND): IntTensor { - checkShapesCompatible(asIntTensor(), arg) - val resBuffer = IntArray(asIntTensor().numElements) { i -> - asIntTensor().mutableBuffer.array()[i] - arg.asIntTensor().mutableBuffer.array()[i] - } - return IntTensor(asIntTensor().shape, resBuffer) - } + override fun StructureND.minus(arg: StructureND): IntTensor = zip(this, arg) { l, r -> l + r } override fun Tensor.minusAssign(value: Int) { - for (i in 0 until asIntTensor().numElements) { - asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + i] -= value - } + mapInPlace { it - value } } override fun Tensor.minusAssign(arg: StructureND) { - checkShapesCompatible(asIntTensor(), arg) - for (i in 0 until asIntTensor().numElements) { - asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + i] -= - arg.asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + i] - } + checkShapesCompatible(this, arg) + mapIndexedInPlace { index, value -> value - arg[index] } } - override fun Int.times(arg: StructureND): IntTensor { - val resBuffer = IntArray(arg.asIntTensor().numElements) { i -> - arg.asIntTensor().mutableBuffer.array()[arg.asIntTensor().bufferStart + i] * this - } - return IntTensor(arg.shape, resBuffer) - } + override fun Int.times(arg: StructureND): IntTensor = arg.map { this@times * it } override fun StructureND.times(arg: Int): IntTensor = arg * asIntTensor() - override fun StructureND.times(arg: StructureND): IntTensor { - checkShapesCompatible(asIntTensor(), arg) - val resBuffer = IntArray(asIntTensor().numElements) { i -> - asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + i] * - arg.asIntTensor().mutableBuffer.array()[arg.asIntTensor().bufferStart + i] - } - return IntTensor(asIntTensor().shape, resBuffer) - } + override fun StructureND.times(arg: StructureND): IntTensor = zip(this, arg) { l, r -> l * r } override fun Tensor.timesAssign(value: Int) { - for (i in 0 until asIntTensor().numElements) { - asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + i] *= value - } + mapInPlace { it * value } } override fun Tensor.timesAssign(arg: StructureND) { - checkShapesCompatible(asIntTensor(), arg) - for (i in 0 until asIntTensor().numElements) { - asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + i] *= - arg.asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + i] - } + checkShapesCompatible(this, arg) + mapIndexedInPlace { index, value -> value * arg[index] } } - override fun StructureND.unaryMinus(): IntTensor { - val resBuffer = IntArray(asIntTensor().numElements) { i -> - asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + i].unaryMinus() - } - return IntTensor(asIntTensor().shape, resBuffer) - } + override fun StructureND.unaryMinus(): IntTensor = map { -it } - override fun Tensor.transpose(i: Int, j: Int): IntTensor { - val ii = asIntTensor().minusIndex(i) - val jj = asIntTensor().minusIndex(j) - checkTranspose(asIntTensor().dimension, ii, jj) - val n = asIntTensor().numElements + 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 = asIntTensor().shape.copyOf() + val resShape = dt.shape.copyOf() resShape[ii] = resShape[jj].also { resShape[jj] = resShape[ii] } - val resTensor = IntTensor(resShape, resBuffer) + val resTensor = IntTensor(resShape, resBuffer.asBuffer()) for (offset in 0 until n) { - val oldMultiIndex = asIntTensor().indices.index(offset) + val oldMultiIndex = dt.indices.index(offset) val newMultiIndex = oldMultiIndex.copyOf() newMultiIndex[ii] = newMultiIndex[jj].also { newMultiIndex[jj] = newMultiIndex[ii] } val linearIndex = resTensor.indices.offset(newMultiIndex) - resTensor.mutableBuffer.array()[linearIndex] = - asIntTensor().mutableBuffer.array()[asIntTensor().bufferStart + offset] + resTensor.source[linearIndex] = dt.source[offset] } return resTensor } override fun Tensor.view(shape: IntArray): IntTensor { checkView(asIntTensor(), shape) - return IntTensor(shape, asIntTensor().mutableBuffer.array(), asIntTensor().bufferStart) + return IntTensor(shape, asIntTensor().source) } override fun Tensor.viewAs(other: StructureND): IntTensor = - asIntTensor().view(other.shape) + view(other.shape) + + override fun StructureND.dot(other: StructureND): IntTensor { + return if (dimension in 0..2 && other.dimension in 0..2) TODO("not implemented") + else error("Only vectors and matrices are allowed in non-broadcasting dot operation") + } override fun diagonalEmbedding( diagonalEntries: Tensor, @@ -374,7 +319,7 @@ public open class IntTensorAlgebra : TensorAlgebra { diagonalEntries.shape.slice(greaterDim - 1 until n - 1).toIntArray() val resTensor = zeros(resShape) - for (i in 0 until diagonalEntries.asIntTensor().numElements) { + for (i in 0 until diagonalEntries.asIntTensor().linearSize) { val multiIndex = diagonalEntries.asIntTensor().indices.index(i) var offset1 = 0 @@ -394,16 +339,27 @@ public open class IntTensorAlgebra : TensorAlgebra { return resTensor.asIntTensor() } - private infix fun Tensor.eq( + /** + * Compares element-wise two int tensors + * + * @param other the tensor to compare with `input` tensor. + * @param epsilon permissible error when comparing two Int values. + * @return true if two tensors have the same shape and elements, false otherwise. + */ + public fun Tensor.eq(other: Tensor): Boolean = + asIntTensor().eq(other) { x, y -> x == y } + + private fun Tensor.eq( other: Tensor, + eqFunction: (Int, Int) -> Boolean, ): Boolean { checkShapesCompatible(asIntTensor(), other) - val n = asIntTensor().numElements - if (n != other.asIntTensor().numElements) { + val n = asIntTensor().linearSize + if (n != other.asIntTensor().linearSize) { return false } for (i in 0 until n) { - if (asIntTensor().mutableBuffer[asIntTensor().bufferStart + i] != other.asIntTensor().mutableBuffer[other.asIntTensor().bufferStart + i]) { + if (!eqFunction(asIntTensor().source[i], other.asIntTensor().source[i])) { return false } } @@ -421,10 +377,12 @@ public open class IntTensorAlgebra : TensorAlgebra { val shape = tensors[0].shape check(tensors.all { it.shape contentEquals shape }) { "Tensors must have same shapes" } val resShape = intArrayOf(tensors.size) + shape - val resBuffer = tensors.flatMap { - it.asIntTensor().mutableBuffer.array().drop(it.asIntTensor().bufferStart).take(it.asIntTensor().numElements) - }.toIntArray() - return IntTensor(resShape, resBuffer, 0) +// val resBuffer: List = tensors.flatMap { +// it.asIntTensor().source.array.drop(it.asIntTensor().bufferStart) +// .take(it.asIntTensor().linearSize) +// } + val resBuffer = tensors.map { it.asIntTensor().source }.concat() + return IntTensor(resShape, resBuffer) } /** @@ -435,14 +393,11 @@ public open class IntTensorAlgebra : TensorAlgebra { */ public fun Tensor.rowsByIndices(indices: IntArray): IntTensor = stack(indices.map { getTensor(it) }) - private inline fun StructureND.fold(foldFunction: (IntArray) -> Int): Int = - foldFunction(asIntTensor().copyArray()) - - private inline fun StructureND.foldDim( + private inline fun StructureND.foldDimToInt( dim: Int, keepDim: Boolean, - foldFunction: (IntArray) -> R, - ): BufferedTensor { + foldFunction: (IntArray) -> Int, + ): IntTensor { check(dim < dimension) { "Dimension $dim out of range $dimension" } val resShape = if (keepDim) { shape.take(dim).toIntArray() + intArrayOf(1) + shape.takeLast(dimension - dim - 1).toIntArray() @@ -451,9 +406,9 @@ public open class IntTensorAlgebra : TensorAlgebra { } val resNumElements = resShape.reduce(Int::times) val init = foldFunction(IntArray(1) { 0 }) - val resTensor = BufferedTensor( + val resTensor = IntTensor( resShape, - MutableBuffer.auto(resNumElements) { init }, 0 + IntBuffer(resNumElements) { init } ) for (index in resTensor.indices) { val prefix = index.take(dim).toIntArray() @@ -465,31 +420,33 @@ public open class IntTensorAlgebra : TensorAlgebra { return resTensor } - override fun StructureND.sum(): Int = asIntTensor().fold { it.sum() } + + override fun StructureND.sum(): Int = reduceElements { it.array.sum() } override fun StructureND.sum(dim: Int, keepDim: Boolean): IntTensor = - foldDim(dim, keepDim) { x -> x.sum() }.asIntTensor() + foldDimToInt(dim, keepDim) { x -> x.sum() } - override fun StructureND.min(): Int = this.fold { it.minOrNull()!! } + override fun StructureND.min(): Int = reduceElements { it.array.min() } override fun StructureND.min(dim: Int, keepDim: Boolean): IntTensor = - foldDim(dim, keepDim) { x -> x.minOrNull()!! }.asIntTensor() + foldDimToInt(dim, keepDim) { x -> x.minOrNull()!! } - override fun StructureND.argMin(dim: Int, keepDim: Boolean): IntTensor = - foldDim(dim, keepDim) { x -> - x.withIndex().minByOrNull { it.value }?.index!! - }.asIntTensor() + override fun StructureND.argMin(dim: Int, keepDim: Boolean): Tensor = foldDimToInt(dim, keepDim) { x -> + x.withIndex().minBy { it.value }.index + } - override fun StructureND.max(): Int = this.fold { it.maxOrNull()!! } + override fun StructureND.max(): Int = reduceElements { it.array.max() } override fun StructureND.max(dim: Int, keepDim: Boolean): IntTensor = - foldDim(dim, keepDim) { x -> x.maxOrNull()!! }.asIntTensor() + foldDimToInt(dim, keepDim) { x -> x.max() } override fun StructureND.argMax(dim: Int, keepDim: Boolean): IntTensor = - foldDim(dim, keepDim) { x -> - x.withIndex().maxByOrNull { it.value }?.index!! - }.asIntTensor() + foldDimToInt(dim, keepDim) { x -> + x.withIndex().maxBy { it.value }.index + } + + public fun StructureND.mean(): Double = sum().toDouble() / indices.linearSize } public val Int.Companion.tensorAlgebra: IntTensorAlgebra get() = IntTensorAlgebra 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 ab97903e4..fee62c79c 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/broadcastUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/broadcastUtils.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.tensors.core.internal +import space.kscience.kmath.structures.asBuffer import space.kscience.kmath.tensors.core.DoubleTensor import kotlin.math.max @@ -24,8 +25,8 @@ internal fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: DoubleTenso } val curLinearIndex = tensor.indices.offset(curMultiIndex) - resTensor.mutableBuffer.array()[linearIndex] = - tensor.mutableBuffer.array()[tensor.bufferStart + curLinearIndex] + resTensor.source[linearIndex] = + tensor.source[curLinearIndex] } } @@ -63,7 +64,7 @@ internal fun broadcastTo(tensor: DoubleTensor, newShape: IntArray): DoubleTensor } val n = newShape.reduce { acc, i -> acc * i } - val resTensor = DoubleTensor(newShape, DoubleArray(n)) + val resTensor = DoubleTensor(newShape, DoubleArray(n).asBuffer()) for (i in tensor.shape.indices) { val curDim = tensor.shape[i] @@ -82,7 +83,7 @@ internal fun broadcastTensors(vararg tensors: DoubleTensor): List val n = totalShape.reduce { acc, i -> acc * i } return tensors.map { tensor -> - val resTensor = DoubleTensor(totalShape, DoubleArray(n)) + val resTensor = DoubleTensor(totalShape, DoubleArray(n).asBuffer()) multiIndexBroadCasting(tensor, resTensor, n) resTensor } @@ -106,17 +107,17 @@ internal fun broadcastOuterTensors(vararg tensors: DoubleTensor): List checkShapesCompatible(a: StructureND, b: StructureND) = +@PublishedApi +internal fun checkShapesCompatible(a: StructureND, b: StructureND): Unit = check(a.shape contentEquals b.shape) { "Incompatible shapes ${a.shape.toList()} and ${b.shape.toList()} " } @@ -50,15 +52,14 @@ internal fun checkSquareMatrix(shape: IntArray) { internal fun DoubleTensorAlgebra.checkSymmetric( tensor: Tensor, epsilon: Double = 1e-6, -) = - check(tensor.eq(tensor.transpose(), epsilon)) { - "Tensor is not symmetric about the last 2 dimensions at precision $epsilon" - } +) = check(tensor.eq(tensor.transposed(), epsilon)) { + "Tensor is not symmetric about the last 2 dimensions at precision $epsilon" +} internal fun DoubleTensorAlgebra.checkPositiveDefinite(tensor: DoubleTensor, epsilon: Double = 1e-6) { checkSymmetric(tensor, epsilon) for (mat in tensor.matrixSequence()) - check(mat.toTensor().detLU().value() > 0.0) { - "Tensor contains matrices which are not positive definite ${mat.toTensor().detLU().value()}" + check(mat.asDoubleTensor().detLU().value() > 0.0) { + "Tensor contains matrices which are not positive definite ${mat.asDoubleTensor().detLU().value()}" } } \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/doubleTensorHelpers.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/doubleTensorHelpers.kt new file mode 100644 index 000000000..9c6f54d61 --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/doubleTensorHelpers.kt @@ -0,0 +1,189 @@ +/* + * Copyright 2018-2022 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.tensors.core.internal + +import space.kscience.kmath.nd.MutableStructure2D +import space.kscience.kmath.nd.Structure2D +import space.kscience.kmath.nd.as2D +import space.kscience.kmath.nd.get +import space.kscience.kmath.operations.asSequence +import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.structures.VirtualBuffer +import space.kscience.kmath.structures.asBuffer +import space.kscience.kmath.structures.indices +import space.kscience.kmath.tensors.core.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 + + +internal fun MutableStructure2D.jacobiHelper( + maxIteration: Int, + epsilon: Double, +): Pair> { + val n = rowNum + val A_ = copyToTensor() + val V = eye(n) + val D = DoubleBuffer(n) { get(it, it) } + val B = DoubleBuffer(n) { get(it, it) } + val Z = DoubleBuffer(n) { 0.0 } + + // assume that buffered tensor is square matrix + operator fun DoubleTensor.get(i: Int, j: Int): Double { + return source[i * shape[0] + j] + } + + operator fun BufferedTensor.set(i: Int, j: Int, value: Double) { + source[i * shape[0] + j] = value + } + + fun maxOffDiagonal(matrix: BufferedTensor): Double { + var maxOffDiagonalElement = 0.0 + for (i in 0 until n - 1) { + for (j in i + 1 until n) { + maxOffDiagonalElement = max(maxOffDiagonalElement, abs(matrix[i, j])) + } + } + return maxOffDiagonalElement + } + + fun rotate(a: BufferedTensor, s: Double, tau: Double, i: Int, j: Int, k: Int, l: Int) { + val g = a[i, j] + val h = a[k, l] + a[i, j] = g - s * (h + g * tau) + a[k, l] = h + s * (g - h * tau) + } + + fun jacobiIteration( + a: BufferedTensor, + v: BufferedTensor, + d: DoubleBuffer, + z: DoubleBuffer, + ) { + for (ip in 0 until n - 1) { + for (iq in ip + 1 until n) { + val g = 100.0 * abs(a[ip, iq]) + + if (g <= epsilon * abs(d[ip]) && g <= epsilon * abs(d[iq])) { + a[ip, iq] = 0.0 + continue + } + + var h = d[iq] - d[ip] + val t = when { + g <= epsilon * abs(h) -> (a[ip, iq]) / h + else -> { + val theta = 0.5 * h / (a[ip, iq]) + val denominator = abs(theta) + sqrt(1.0 + theta * theta) + if (theta < 0.0) -1.0 / denominator else 1.0 / denominator + } + } + + val c = 1.0 / sqrt(1 + t * t) + val s = t * c + val tau = s / (1.0 + c) + h = t * a[ip, iq] + z[ip] -= h + z[iq] += h + d[ip] -= h + d[iq] += h + a[ip, iq] = 0.0 + + for (j in 0 until ip) { + rotate(a, s, tau, j, ip, j, iq) + } + for (j in (ip + 1) until iq) { + rotate(a, s, tau, ip, j, j, iq) + } + for (j in (iq + 1) until n) { + rotate(a, s, tau, ip, j, iq, j) + } + for (j in 0 until n) { + rotate(v, s, tau, j, ip, j, iq) + } + } + } + } + + fun updateDiagonal( + d: DoubleBuffer, + z: DoubleBuffer, + b: DoubleBuffer, + ) { + for (ip in 0 until d.size) { + b[ip] += z[ip] + d[ip] = b[ip] + z[ip] = 0.0 + } + } + + var sm = maxOffDiagonal(A_) + for (iteration in 0 until maxIteration) { + if (sm < epsilon) { + break + } + + jacobiIteration(A_, V, D, Z) + updateDiagonal(D, Z, B) + sm = maxOffDiagonal(A_) + } + + // TODO sort eigenvalues + return D to V.as2D() +} + +/** + * Concatenate a list of arrays + */ +internal fun List.concat(): DoubleBuffer { + val array = DoubleArray(sumOf { it.size }) + var pointer = 0 + while (pointer < array.size) { + for (bufferIndex in indices) { + val buffer = get(bufferIndex) + for (innerIndex in buffer.indices) { + array[pointer] = buffer[innerIndex] + pointer++ + } + } + } + return array.asBuffer() +} + +internal val DoubleTensor.vectors: VirtualBuffer + get() { + val n = shape.size + val vectorOffset = shape[n - 1] + val vectorShape = intArrayOf(shape.last()) + + return VirtualBuffer(linearSize / vectorOffset) { index -> + val offset = index * vectorOffset + DoubleTensor(vectorShape, source.view(offset)) + } + } + + +internal fun DoubleTensor.vectorSequence(): Sequence = vectors.asSequence() + + +internal val DoubleTensor.matrices: VirtualBuffer + get(){ + val n = shape.size + check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n" } + val matrixOffset = shape[n - 1] * shape[n - 2] + val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) + + return VirtualBuffer(linearSize / matrixOffset) { index -> + val offset = index * matrixOffset + DoubleTensor(matrixShape, source.view(offset)) + } +} + +internal fun DoubleTensor.matrixSequence(): Sequence = matrices.asSequence() \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/intTensorHelpers.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/intTensorHelpers.kt new file mode 100644 index 000000000..93229c2d4 --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/intTensorHelpers.kt @@ -0,0 +1,64 @@ +/* + * Copyright 2018-2022 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.tensors.core.internal + +import space.kscience.kmath.operations.asSequence +import space.kscience.kmath.structures.IntBuffer +import space.kscience.kmath.structures.VirtualBuffer +import space.kscience.kmath.structures.asBuffer +import space.kscience.kmath.structures.indices +import space.kscience.kmath.tensors.core.IntTensor +import space.kscience.kmath.tensors.core.OffsetIntBuffer + +/** + * Concatenate a list of arrays + */ +internal fun List.concat(): IntBuffer { + val array = IntArray(sumOf { it.size }) + var pointer = 0 + while (pointer < array.size) { + for (bufferIndex in indices) { + val buffer = get(bufferIndex) + for (innerIndex in buffer.indices) { + array[pointer] = buffer[innerIndex] + pointer++ + } + } + } + return array.asBuffer() +} + + +internal val IntTensor.vectors: VirtualBuffer + get() { + val n = shape.size + val vectorOffset = shape[n - 1] + val vectorShape = intArrayOf(shape.last()) + + return VirtualBuffer(linearSize / vectorOffset) { index -> + val offset = index * vectorOffset + IntTensor(vectorShape, source.view(offset)) + } + } + + +internal fun IntTensor.vectorSequence(): Sequence = vectors.asSequence() + + +internal val IntTensor.matrices: VirtualBuffer + get(){ + val n = shape.size + check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n" } + val matrixOffset = shape[n - 1] * shape[n - 2] + val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) + + return VirtualBuffer(linearSize / matrixOffset) { index -> + val offset = index * matrixOffset + IntTensor(matrixShape, source.view(offset)) + } + } + +internal fun IntTensor.matrixSequence(): Sequence = matrices.asSequence() \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt index ec529590f..9047ba29e 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/linUtils.kt @@ -5,75 +5,33 @@ package space.kscience.kmath.tensors.core.internal -import space.kscience.kmath.nd.MutableStructure1D -import space.kscience.kmath.nd.MutableStructure2D -import space.kscience.kmath.nd.as1D -import space.kscience.kmath.nd.as2D -import space.kscience.kmath.operations.asSequence +import space.kscience.kmath.nd.* import space.kscience.kmath.operations.invoke -import space.kscience.kmath.structures.VirtualBuffer -import space.kscience.kmath.tensors.core.BufferedTensor -import space.kscience.kmath.tensors.core.DoubleTensor -import space.kscience.kmath.tensors.core.DoubleTensorAlgebra -import space.kscience.kmath.tensors.core.IntTensor +import space.kscience.kmath.structures.IntBuffer +import space.kscience.kmath.structures.asBuffer +import space.kscience.kmath.structures.indices +import space.kscience.kmath.tensors.core.* import kotlin.math.abs import kotlin.math.min import kotlin.math.sqrt -internal val BufferedTensor.vectors: VirtualBuffer> - get() { - val n = shape.size - val vectorOffset = shape[n - 1] - val vectorShape = intArrayOf(shape.last()) - - return VirtualBuffer(numElements / vectorOffset) { index -> - val offset = index * vectorOffset - BufferedTensor(vectorShape, mutableBuffer, bufferStart + offset) - } - } - - -internal fun BufferedTensor.vectorSequence(): Sequence> = vectors.asSequence() - -/** - * A random access alternative to [matrixSequence] - */ -internal val BufferedTensor.matrices: VirtualBuffer> - get() { - val n = shape.size - check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n" } - val matrixOffset = shape[n - 1] * shape[n - 2] - val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) - - return VirtualBuffer(numElements / matrixOffset) { index -> - val offset = index * matrixOffset - BufferedTensor(matrixShape, mutableBuffer, bufferStart + offset) - } - } - -internal fun BufferedTensor.matrixSequence(): Sequence> = matrices.asSequence() - internal fun dotTo( a: BufferedTensor, b: BufferedTensor, res: BufferedTensor, l: Int, m: Int, n: Int, ) { - val aStart = a.bufferStart - val bStart = b.bufferStart - val resStart = res.bufferStart - - val aBuffer = a.mutableBuffer - val bBuffer = b.mutableBuffer - val resBuffer = res.mutableBuffer + val aBuffer = a.source + val bBuffer = b.source + val resBuffer = res.source for (i in 0 until l) { for (j in 0 until n) { var curr = 0.0 for (k in 0 until m) { - curr += aBuffer[aStart + i * m + k] * bBuffer[bStart + k * n + j] + curr += aBuffer[i * m + k] * bBuffer[k * n + j] } - resBuffer[resStart + i * n + j] = curr + resBuffer[i * n + j] = curr } } } @@ -129,7 +87,7 @@ internal fun luHelper( return false } -internal fun BufferedTensor.setUpPivots(): IntTensor { +internal fun StructureND.setUpPivots(): IntTensor { val n = this.shape.size val m = this.shape.last() val pivotsShape = IntArray(n - 1) { i -> this.shape[i] } @@ -137,17 +95,17 @@ internal fun BufferedTensor.setUpPivots(): IntTensor { return IntTensor( pivotsShape, - IntArray(pivotsShape.reduce(Int::times)) { 0 } + IntBuffer(pivotsShape.reduce(Int::times)) { 0 } ) } internal fun DoubleTensorAlgebra.computeLU( - tensor: DoubleTensor, + tensor: StructureND, epsilon: Double, ): Pair? { checkSquareMatrix(tensor.shape) - val luTensor = tensor.copy() + val luTensor = tensor.copyToTensor() val pivotsTensor = tensor.setUpPivots() for ((lu, pivots) in luTensor.matrixSequence().zip(pivotsTensor.vectorSequence())) @@ -253,8 +211,8 @@ internal fun DoubleTensorAlgebra.qrHelper( checkSquareMatrix(matrix.shape) val n = matrix.shape[0] val qM = q.as2D() - val matrixT = matrix.transpose(0, 1) - val qT = q.transpose(0, 1) + val matrixT = matrix.transposed(0, 1) + val qT = q.transposed(0, 1) for (j in 0 until n) { val v = matrixT.getTensor(j) @@ -280,10 +238,10 @@ internal fun DoubleTensorAlgebra.svd1d(a: DoubleTensor, epsilon: Double = 1e-10) var v: DoubleTensor val b: DoubleTensor if (n > m) { - b = a.transpose(0, 1).dot(a) + b = a.transposed(0, 1).dot(a) v = DoubleTensor(intArrayOf(m), getRandomUnitVector(m, 0)) } else { - b = a.dot(a.transpose(0, 1)) + b = a.dot(a.transposed(0, 1)) v = DoubleTensor(intArrayOf(n), getRandomUnitVector(n, 0)) } @@ -308,7 +266,7 @@ internal fun DoubleTensorAlgebra.svdHelper( val (matrixU, matrixS, matrixV) = USV for (k in 0 until min(n, m)) { - var a = matrix.copy() + var a = matrix.copyToTensor() for ((singularValue, u, v) in res.slice(0 until k)) { val outerProduct = DoubleArray(u.shape[0] * v.shape[0]) for (i in 0 until u.shape[0]) { @@ -316,7 +274,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)) + a = a - singularValue.times(DoubleTensor(intArrayOf(u.shape[0], v.shape[0]), outerProduct.asBuffer())) } var v: DoubleTensor var u: DoubleTensor @@ -328,7 +286,7 @@ internal fun DoubleTensorAlgebra.svdHelper( u = u.times(1.0 / norm) } else { u = svd1d(a, epsilon) - v = matrix.transpose(0, 1).dot(u) + v = matrix.transposed(0, 1).dot(u) norm = DoubleTensorAlgebra { (v dot v).sqrt().value() } v = v.times(1.0 / norm) } @@ -337,15 +295,15 @@ internal fun DoubleTensorAlgebra.svdHelper( } val s = res.map { it.first }.toDoubleArray() - val uBuffer = res.map { it.second }.flatMap { it.mutableBuffer.array().toList() }.toDoubleArray() - val vBuffer = res.map { it.third }.flatMap { it.mutableBuffer.array().toList() }.toDoubleArray() + val uBuffer = res.map { it.second.source }.concat() + val vBuffer = res.map { it.third.source }.concat() for (i in uBuffer.indices) { - matrixU.mutableBuffer.array()[matrixU.bufferStart + i] = uBuffer[i] + matrixU.source[i] = uBuffer[i] } for (i in s.indices) { - matrixS.mutableBuffer.array()[matrixS.bufferStart + i] = s[i] + matrixS.source[i] = s[i] } for (i in vBuffer.indices) { - matrixV.mutableBuffer.array()[matrixV.bufferStart + i] = vBuffer[i] + matrixV.source[i] = vBuffer[i] } } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.kt deleted file mode 100644 index e7704b257..000000000 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/tensorCastsUtils.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.tensors.core.internal - -import space.kscience.kmath.nd.MutableBufferND -import space.kscience.kmath.nd.StructureND -import space.kscience.kmath.structures.asMutableBuffer -import space.kscience.kmath.tensors.core.BufferedTensor -import space.kscience.kmath.tensors.core.DoubleTensor -import space.kscience.kmath.tensors.core.IntTensor -import space.kscience.kmath.tensors.core.TensorLinearStructure - -internal fun BufferedTensor.toTensor(): IntTensor = - IntTensor(this.shape, this.mutableBuffer.array(), this.bufferStart) - -internal fun BufferedTensor.toTensor(): DoubleTensor = - DoubleTensor(this.shape, this.mutableBuffer.array(), this.bufferStart) - -internal fun StructureND.copyToBufferedTensor(): BufferedTensor = - BufferedTensor( - this.shape, - TensorLinearStructure(this.shape).asSequence().map(this::get).toMutableList().asMutableBuffer(), - 0 - ) - -internal fun StructureND.toBufferedTensor(): BufferedTensor = when (this) { - is BufferedTensor -> this - is MutableBufferND -> if (this.indices == TensorLinearStructure(this.shape)) { - BufferedTensor(this.shape, this.buffer, 0) - } else { - this.copyToBufferedTensor() - } - else -> this.copyToBufferedTensor() -} 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 8a96d516f..daafdaa58 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/utils.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/utils.kt @@ -6,41 +6,25 @@ package space.kscience.kmath.tensors.core.internal import space.kscience.kmath.nd.as1D +import space.kscience.kmath.operations.DoubleBufferOps.Companion.map import space.kscience.kmath.operations.toMutableList import space.kscience.kmath.samplers.GaussianSampler import space.kscience.kmath.stat.RandomGenerator -import space.kscience.kmath.structures.* +import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.tensors.core.BufferedTensor import space.kscience.kmath.tensors.core.DoubleTensor import kotlin.math.* -/** - * Returns a reference to [IntArray] containing all the elements of this [Buffer] or copy the data. - */ -internal fun Buffer.array(): IntArray = when (this) { - is IntBuffer -> array - else -> this.toIntArray() -} - -/** - * Returns a reference to [DoubleArray] containing all the elements of this [Buffer] or copy the data. - */ -@PublishedApi -internal fun Buffer.array(): DoubleArray = when (this) { - is DoubleBuffer -> array - else -> this.toDoubleArray() -} - -internal fun getRandomNormals(n: Int, seed: Long): DoubleArray { +internal fun getRandomNormals(n: Int, seed: Long): DoubleBuffer { val distribution = GaussianSampler(0.0, 1.0) val generator = RandomGenerator.default(seed) - return distribution.sample(generator).nextBufferBlocking(n).toDoubleArray() + return distribution.sample(generator).nextBufferBlocking(n) } -internal fun getRandomUnitVector(n: Int, seed: Long): DoubleArray { - val unnorm = getRandomNormals(n, seed) - val norm = sqrt(unnorm.sumOf { it * it }) - return unnorm.map { it / norm }.toDoubleArray() +internal fun getRandomUnitVector(n: Int, seed: Long): DoubleBuffer { + val unnorm: DoubleBuffer = getRandomNormals(n, seed) + val norm = sqrt(unnorm.array.sumOf { it * it }) + return unnorm.map { it / norm } } internal fun minusIndexFrom(n: Int, i: Int): Int = if (i >= 0) i else { @@ -71,6 +55,7 @@ internal fun format(value: Double, digits: Int = 4): String = buildString { append("e+") append(order) } + else -> { append('e') append(order) @@ -116,7 +101,7 @@ internal fun DoubleTensor.toPrettyString(): String = buildString { } offset += vectorSize - if (this@toPrettyString.numElements == offset) { + if (this@toPrettyString.linearSize == offset) { break } diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt deleted file mode 100644 index 1c914d474..000000000 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorCasts.kt +++ /dev/null @@ -1,46 +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.StructureND -import space.kscience.kmath.tensors.api.Tensor -import space.kscience.kmath.tensors.core.internal.toBufferedTensor -import space.kscience.kmath.tensors.core.internal.toTensor - -/** - * Casts [Tensor] of [Double] to [DoubleTensor] - */ -public fun StructureND.asDoubleTensor(): DoubleTensor = when (this) { - is DoubleTensor -> this - else -> this.toBufferedTensor().toTensor() -} - -/** - * Casts [Tensor] of [Int] to [IntTensor] - */ -public fun StructureND.asIntTensor(): IntTensor = when (this) { - is IntTensor -> this - else -> this.toBufferedTensor().toTensor() -} - -/** - * Returns a copy-protected [DoubleArray] of tensor elements - */ -public fun DoubleTensor.copyArray(): DoubleArray { - //TODO use ArrayCopy - return DoubleArray(numElements) { i -> - mutableBuffer[bufferStart + i] - } -} - -/** - * Returns a copy-protected [IntArray] of tensor elements - */ -public fun IntTensor.copyArray(): IntArray { - return IntArray(numElements) { i -> - mutableBuffer[bufferStart + i] - } -} diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorTransform.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorTransform.kt new file mode 100644 index 000000000..30a828d6a --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorTransform.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2018-2022 KMath 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.StructureND +import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.structures.asBuffer +import space.kscience.kmath.tensors.api.Tensor + + +public fun StructureND.copyToTensor(): DoubleTensor = if (this is DoubleTensor) { + DoubleTensor(shape, source.copy()) +} else { + DoubleTensor( + shape, + TensorLinearStructure(this.shape).map(this::get).toDoubleArray().asBuffer(), + ) +} + +public fun StructureND.toDoubleTensor(): DoubleTensor { + return if (this is IntTensor) { + DoubleTensor( + shape, + DoubleBuffer(linearSize) { source[it].toDouble() } + ) + } else { + val tensor = DoubleTensorAlgebra.zeroesLike(this) + indices.forEach { + tensor[it] = get(it).toDouble() + } + return tensor + } +} + +/** + * Casts [Tensor] of [Double] to [DoubleTensor] + */ +public fun StructureND.asDoubleTensor(): DoubleTensor = when (this) { + is DoubleTensor -> this + else -> copyToTensor() +} + +/** + * Casts [Tensor] of [Int] to [IntTensor] + */ +public fun StructureND.asIntTensor(): IntTensor = when (this) { + is IntTensor -> this + else -> IntTensor( + this.shape, + TensorLinearStructure(this.shape).map(this::get).toIntArray().asBuffer() + ) +} \ No newline at end of file diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt index 67d5f9a96..6a99b9ba8 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestBroadcasting.kt @@ -6,7 +6,10 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.internal.* +import space.kscience.kmath.tensors.core.internal.broadcastOuterTensors +import space.kscience.kmath.tensors.core.internal.broadcastShapes +import space.kscience.kmath.tensors.core.internal.broadcastTensors +import space.kscience.kmath.tensors.core.internal.broadcastTo import kotlin.test.Test import kotlin.test.assertTrue @@ -34,7 +37,7 @@ internal class TestBroadcasting { val res = broadcastTo(tensor2, tensor1.shape) assertTrue(res.shape contentEquals intArrayOf(2, 3)) - assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) + assertTrue(res.source contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) } @Test @@ -49,9 +52,9 @@ internal class TestBroadcasting { assertTrue(res[1].shape contentEquals intArrayOf(1, 2, 3)) assertTrue(res[2].shape contentEquals intArrayOf(1, 2, 3)) - assertTrue(res[0].mutableBuffer.array() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - assertTrue(res[1].mutableBuffer.array() contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) - assertTrue(res[2].mutableBuffer.array() contentEquals doubleArrayOf(500.0, 500.0, 500.0, 500.0, 500.0, 500.0)) + assertTrue(res[0].source contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + assertTrue(res[1].source contentEquals doubleArrayOf(10.0, 20.0, 30.0, 10.0, 20.0, 30.0)) + assertTrue(res[2].source contentEquals doubleArrayOf(500.0, 500.0, 500.0, 500.0, 500.0, 500.0)) } @Test @@ -66,15 +69,15 @@ internal class TestBroadcasting { assertTrue(res[1].shape contentEquals intArrayOf(1, 1, 3)) assertTrue(res[2].shape contentEquals intArrayOf(1, 1, 1)) - assertTrue(res[0].mutableBuffer.array() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - assertTrue(res[1].mutableBuffer.array() contentEquals doubleArrayOf(10.0, 20.0, 30.0)) - assertTrue(res[2].mutableBuffer.array() contentEquals doubleArrayOf(500.0)) + assertTrue(res[0].source contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + assertTrue(res[1].source contentEquals doubleArrayOf(10.0, 20.0, 30.0)) + assertTrue(res[2].source contentEquals doubleArrayOf(500.0)) } @Test fun testBroadcastOuterTensorsShapes() = DoubleTensorAlgebra { - val tensor1 = fromArray(intArrayOf(2, 1, 3, 2, 3), DoubleArray(2 * 1 * 3 * 2 * 3) {0.0}) - val tensor2 = fromArray(intArrayOf(4, 2, 5, 1, 3, 3), DoubleArray(4 * 2 * 5 * 1 * 3 * 3) {0.0}) + val tensor1 = fromArray(intArrayOf(2, 1, 3, 2, 3), DoubleArray(2 * 1 * 3 * 2 * 3) { 0.0 }) + val tensor2 = fromArray(intArrayOf(4, 2, 5, 1, 3, 3), DoubleArray(4 * 2 * 5 * 1 * 3 * 3) { 0.0 }) val tensor3 = fromArray(intArrayOf(1, 1), doubleArrayOf(500.0)) val res = broadcastOuterTensors(tensor1, tensor2, tensor3) @@ -95,16 +98,16 @@ internal class TestBroadcasting { val tensor32 = tensor3 - tensor2 assertTrue(tensor21.shape contentEquals intArrayOf(2, 3)) - assertTrue(tensor21.mutableBuffer.array() contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0)) + assertTrue(tensor21.source contentEquals doubleArrayOf(9.0, 18.0, 27.0, 6.0, 15.0, 24.0)) assertTrue(tensor31.shape contentEquals intArrayOf(1, 2, 3)) assertTrue( - tensor31.mutableBuffer.array() + tensor31.source contentEquals doubleArrayOf(499.0, 498.0, 497.0, 496.0, 495.0, 494.0) ) assertTrue(tensor32.shape contentEquals intArrayOf(1, 1, 3)) - assertTrue(tensor32.mutableBuffer.array() contentEquals doubleArrayOf(490.0, 480.0, 470.0)) + assertTrue(tensor32.source contentEquals doubleArrayOf(490.0, 480.0, 470.0)) } } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt index c777273f3..4bc2e3bdb 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleAnalyticTensorAlgebra.kt @@ -6,6 +6,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.operations.invoke +import space.kscience.kmath.structures.asBuffer import kotlin.math.* import kotlin.test.Test import kotlin.test.assertTrue @@ -20,14 +21,14 @@ internal class TestDoubleAnalyticTensorAlgebra { 3.23, 133.7, 25.3, 100.3, 11.0, 12.012 ) - val tensor = DoubleTensor(shape, buffer) + val tensor = DoubleTensor(shape, buffer.asBuffer()) fun DoubleArray.fmap(transform: (Double) -> Double): DoubleArray { return this.map(transform).toDoubleArray() } fun expectedTensor(transform: (Double) -> Double): DoubleTensor { - return DoubleTensor(shape, buffer.fmap(transform)) + return DoubleTensor(shape, buffer.fmap(transform).asBuffer()) } @Test @@ -106,58 +107,74 @@ internal class TestDoubleAnalyticTensorAlgebra { 1.0, 2.0, -3.0, 4.0 ) - val tensor2 = DoubleTensor(shape2, buffer2) + val tensor2 = DoubleTensor(shape2, buffer2.asBuffer()) @Test fun testMin() = DoubleTensorAlgebra { assertTrue { tensor2.min() == -3.0 } - assertTrue { tensor2.min(0, true) eq fromArray( - intArrayOf(1, 2), - doubleArrayOf(-3.0, 2.0) - )} - assertTrue { tensor2.min(1, false) eq fromArray( - intArrayOf(2), - doubleArrayOf(1.0, -3.0) - )} + assertTrue { + tensor2.min(0, true) eq fromArray( + intArrayOf(1, 2), + doubleArrayOf(-3.0, 2.0) + ) + } + assertTrue { + tensor2.min(1, false) eq fromArray( + intArrayOf(2), + doubleArrayOf(1.0, -3.0) + ) + } } @Test fun testMax() = DoubleTensorAlgebra { assertTrue { tensor2.max() == 4.0 } - assertTrue { tensor2.max(0, true) eq fromArray( - intArrayOf(1, 2), - doubleArrayOf(1.0, 4.0) - )} - assertTrue { tensor2.max(1, false) eq fromArray( - intArrayOf(2), - doubleArrayOf(2.0, 4.0) - )} + assertTrue { + tensor2.max(0, true) eq fromArray( + intArrayOf(1, 2), + doubleArrayOf(1.0, 4.0) + ) + } + assertTrue { + tensor2.max(1, false) eq fromArray( + intArrayOf(2), + doubleArrayOf(2.0, 4.0) + ) + } } @Test fun testSum() = DoubleTensorAlgebra { assertTrue { tensor2.sum() == 4.0 } - assertTrue { tensor2.sum(0, true) eq fromArray( - intArrayOf(1, 2), - doubleArrayOf(-2.0, 6.0) - )} - assertTrue { tensor2.sum(1, false) eq fromArray( - intArrayOf(2), - doubleArrayOf(3.0, 1.0) - )} + assertTrue { + tensor2.sum(0, true) eq fromArray( + intArrayOf(1, 2), + doubleArrayOf(-2.0, 6.0) + ) + } + assertTrue { + tensor2.sum(1, false) eq fromArray( + intArrayOf(2), + doubleArrayOf(3.0, 1.0) + ) + } } @Test fun testMean() = DoubleTensorAlgebra { assertTrue { tensor2.mean() == 1.0 } - assertTrue { tensor2.mean(0, true) eq fromArray( - intArrayOf(1, 2), - doubleArrayOf(-1.0, 3.0) - )} - assertTrue { tensor2.mean(1, false) eq fromArray( - intArrayOf(2), - doubleArrayOf(1.5, 0.5) - )} + assertTrue { + tensor2.mean(0, true) eq fromArray( + intArrayOf(1, 2), + doubleArrayOf(-1.0, 3.0) + ) + } + assertTrue { + tensor2.mean(1, false) eq fromArray( + intArrayOf(2), + doubleArrayOf(1.5, 0.5) + ) + } } } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt index 5b226bd5d..1c23cff18 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleLinearOpsAlgebra.kt @@ -6,7 +6,6 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.internal.array import space.kscience.kmath.tensors.core.internal.svd1d import kotlin.math.abs import kotlin.test.Test @@ -142,11 +141,11 @@ internal class TestDoubleLinearOpsTensorAlgebra { @Test fun testCholesky() = DoubleTensorAlgebra { val tensor = randomNormal(intArrayOf(2, 5, 5), 0) - val sigma = (tensor matmul tensor.transpose()) + diagonalEmbedding( + val sigma = (tensor matmul tensor.transposed()) + diagonalEmbedding( fromArray(intArrayOf(2, 5), DoubleArray(10) { 0.1 }) ) val low = sigma.cholesky() - val sigmChol = low matmul low.transpose() + val sigmChol = low matmul low.transposed() assertTrue(sigma.eq(sigmChol)) } @@ -157,12 +156,12 @@ internal class TestDoubleLinearOpsTensorAlgebra { val res = svd1d(tensor2) assertTrue(res.shape contentEquals intArrayOf(2)) - assertTrue { abs(abs(res.mutableBuffer.array()[res.bufferStart]) - 0.386) < 0.01 } - assertTrue { abs(abs(res.mutableBuffer.array()[res.bufferStart + 1]) - 0.922) < 0.01 } + assertTrue { abs(abs(res.source[0]) - 0.386) < 0.01 } + assertTrue { abs(abs(res.source[1]) - 0.922) < 0.01 } } @Test - fun testSVD() = DoubleTensorAlgebra{ + fun testSVD() = DoubleTensorAlgebra { testSVDFor(fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))) testSVDFor(fromArray(intArrayOf(2, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0))) } @@ -171,16 +170,16 @@ internal class TestDoubleLinearOpsTensorAlgebra { fun testBatchedSVD() = DoubleTensorAlgebra { val tensor = randomNormal(intArrayOf(2, 5, 3), 0) val (tensorU, tensorS, tensorV) = tensor.svd() - val tensorSVD = tensorU matmul (diagonalEmbedding(tensorS) matmul tensorV.transpose()) + val tensorSVD = tensorU matmul (diagonalEmbedding(tensorS) matmul tensorV.transposed()) assertTrue(tensor.eq(tensorSVD)) } @Test fun testBatchedSymEig() = DoubleTensorAlgebra { val tensor = randomNormal(shape = intArrayOf(2, 3, 3), 0) - val tensorSigma = tensor + tensor.transpose() + val tensorSigma = tensor + tensor.transposed() val (tensorS, tensorV) = tensorSigma.symEig() - val tensorSigmaCalc = tensorV matmul (diagonalEmbedding(tensorS) matmul tensorV.transpose()) + val tensorSigmaCalc = tensorV matmul (diagonalEmbedding(tensorS) matmul tensorV.transposed()) assertTrue(tensorSigma.eq(tensorSigmaCalc)) } @@ -194,7 +193,7 @@ private fun DoubleTensorAlgebra.testSVDFor(tensor: DoubleTensor, epsilon: Double val tensorSVD = svd.first .dot( diagonalEmbedding(svd.second) - .dot(svd.third.transpose()) + .dot(svd.third.transposed()) ) assertTrue(tensor.eq(tensorSVD, epsilon)) diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt index efdf6ba81..a36f32ac9 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 @@ -13,10 +13,7 @@ import space.kscience.kmath.nd.as2D import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.toDoubleArray -import space.kscience.kmath.tensors.core.internal.array import space.kscience.kmath.tensors.core.internal.matrixSequence -import space.kscience.kmath.tensors.core.internal.toBufferedTensor -import space.kscience.kmath.tensors.core.internal.toTensor import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue @@ -37,7 +34,7 @@ internal class TestDoubleTensor { assertEquals(tensor[intArrayOf(0, 1)], 5.8) assertTrue( tensor.elements().map { it.second }.toList() - .toDoubleArray() contentEquals tensor.mutableBuffer.toDoubleArray() + .toDoubleArray() contentEquals tensor.source.toDoubleArray() ) } @@ -57,9 +54,9 @@ internal class TestDoubleTensor { assertEquals(tensor[intArrayOf(0, 1, 0)], 109.56) tensor.matrixSequence().forEach { - val a = it.toTensor() + val a = it.asDoubleTensor() val secondRow = a.getTensor(1).as1D() - val secondColumn = a.transpose(0, 1).getTensor(1).as1D() + val secondColumn = a.transposed(0, 1).getTensor(1).as1D() assertEquals(secondColumn[0], 77.89) assertEquals(secondRow[1], secondColumn[1]) } @@ -72,16 +69,16 @@ internal class TestDoubleTensor { val doubleArray = DoubleBuffer(doubleArrayOf(1.0, 2.0, 3.0)) // create ND buffers, no data is copied - val ndArray = MutableBufferND(DefaultStrides(intArrayOf(3)), doubleArray) + val ndArray: MutableBufferND = MutableBufferND(DefaultStrides(intArrayOf(3)), doubleArray) // map to tensors - val bufferedTensorArray = ndArray.toBufferedTensor() // strides are flipped so data copied - val tensorArray = bufferedTensorArray.toTensor() // data not contiguous so copied again + val bufferedTensorArray = ndArray.asDoubleTensor() // strides are flipped so data copied + val tensorArray = bufferedTensorArray.asDoubleTensor() // data not contiguous so copied again val tensorArrayPublic = ndArray.asDoubleTensor() // public API, data copied twice val sharedTensorArray = tensorArrayPublic.asDoubleTensor() // no data copied by matching type - assertTrue(tensorArray.mutableBuffer.array() contentEquals sharedTensorArray.mutableBuffer.array()) + assertTrue(tensorArray.source contentEquals sharedTensorArray.source) tensorArray[intArrayOf(0)] = 55.9 assertEquals(tensorArrayPublic[intArrayOf(0)], 1.0) 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 28c327973..79b199471 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,9 +6,10 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.nd.get import space.kscience.kmath.operations.invoke -import space.kscience.kmath.tensors.core.internal.array import kotlin.test.Test +import kotlin.test.assertEquals import kotlin.test.assertFalse import kotlin.test.assertTrue @@ -18,55 +19,55 @@ internal class TestDoubleTensorAlgebra { fun testDoublePlus() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(2), doubleArrayOf(1.0, 2.0)) val res = 10.0 + tensor - assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(11.0, 12.0)) + assertTrue(res.source contentEquals doubleArrayOf(11.0, 12.0)) } @Test fun testDoubleDiv() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(2), doubleArrayOf(2.0, 4.0)) - val res = 2.0/tensor - assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(1.0, 0.5)) + val res = 2.0 / tensor + assertTrue(res.source contentEquals doubleArrayOf(1.0, 0.5)) } @Test fun testDivDouble() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(2), doubleArrayOf(10.0, 5.0)) val res = tensor / 2.5 - assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(4.0, 2.0)) + assertTrue(res.source contentEquals doubleArrayOf(4.0, 2.0)) } @Test fun testTranspose1x1() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(1), doubleArrayOf(0.0)) - val res = tensor.transpose(0, 0) + val res = tensor.transposed(0, 0) - assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(0.0)) + assertTrue(res.source contentEquals doubleArrayOf(0.0)) assertTrue(res.shape contentEquals intArrayOf(1)) } @Test fun testTranspose3x2() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val res = tensor.transpose(1, 0) + val res = tensor.transposed(1, 0) - assertTrue(res.mutableBuffer.array() contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0)) + assertTrue(res.source contentEquals doubleArrayOf(1.0, 3.0, 5.0, 2.0, 4.0, 6.0)) assertTrue(res.shape contentEquals intArrayOf(2, 3)) } @Test fun testTranspose1x2x3() = DoubleTensorAlgebra { val tensor = fromArray(intArrayOf(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - val res01 = tensor.transpose(0, 1) - val res02 = tensor.transpose(-3, 2) - val res12 = tensor.transpose() + val res01 = tensor.transposed(0, 1) + val res02 = tensor.transposed(-3, 2) + val res12 = tensor.transposed() assertTrue(res01.shape contentEquals intArrayOf(2, 1, 3)) assertTrue(res02.shape contentEquals intArrayOf(3, 2, 1)) assertTrue(res12.shape contentEquals intArrayOf(1, 3, 2)) - assertTrue(res01.mutableBuffer.array() contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) - assertTrue(res02.mutableBuffer.array() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) - assertTrue(res12.mutableBuffer.array() contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) + assertTrue(res01.source contentEquals doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + assertTrue(res02.source contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) + assertTrue(res12.source contentEquals doubleArrayOf(1.0, 4.0, 2.0, 5.0, 3.0, 6.0)) } @Test @@ -97,8 +98,8 @@ internal class TestDoubleTensorAlgebra { assignResult += tensorC assignResult += -39.4 - assertTrue(expected.mutableBuffer.array() contentEquals result.mutableBuffer.array()) - assertTrue(expected.mutableBuffer.array() contentEquals assignResult.mutableBuffer.array()) + assertTrue(expected.source contentEquals result.source) + assertTrue(expected.source contentEquals assignResult.source) } @Test @@ -111,26 +112,28 @@ internal class TestDoubleTensorAlgebra { val tensor5 = fromArray(intArrayOf(2, 3, 3), (1..18).map { 1 + it.toDouble() }.toDoubleArray()) val res12 = tensor1.dot(tensor2) - assertTrue(res12.mutableBuffer.array() contentEquals doubleArrayOf(140.0, 320.0)) + assertTrue(res12.source contentEquals doubleArrayOf(140.0, 320.0)) assertTrue(res12.shape contentEquals intArrayOf(2)) val res32 = tensor3.matmul(tensor2) - assertTrue(res32.mutableBuffer.array() contentEquals doubleArrayOf(-140.0)) + assertTrue(res32.source contentEquals doubleArrayOf(-140.0)) assertTrue(res32.shape contentEquals intArrayOf(1, 1)) val res22 = tensor2.dot(tensor2) - assertTrue(res22.mutableBuffer.array() contentEquals doubleArrayOf(1400.0)) + assertTrue(res22.source contentEquals doubleArrayOf(1400.0)) assertTrue(res22.shape contentEquals intArrayOf(1)) val res11 = tensor1.dot(tensor11) - assertTrue(res11.mutableBuffer.array() contentEquals doubleArrayOf(22.0, 28.0, 49.0, 64.0)) + assertTrue(res11.source contentEquals doubleArrayOf(22.0, 28.0, 49.0, 64.0)) assertTrue(res11.shape contentEquals intArrayOf(2, 2)) val res45 = tensor4.matmul(tensor5) - assertTrue(res45.mutableBuffer.array() contentEquals doubleArrayOf( - 36.0, 42.0, 48.0, 81.0, 96.0, 111.0, 126.0, 150.0, 174.0, - 468.0, 501.0, 534.0, 594.0, 636.0, 678.0, 720.0, 771.0, 822.0 - )) + assertTrue( + res45.source contentEquals doubleArrayOf( + 36.0, 42.0, 48.0, 81.0, 96.0, 111.0, 126.0, 150.0, 174.0, + 468.0, 501.0, 534.0, 594.0, 636.0, 678.0, 720.0, 771.0, 822.0 + ) + ) assertTrue(res45.shape contentEquals intArrayOf(2, 3, 3)) } @@ -140,31 +143,44 @@ internal class TestDoubleTensorAlgebra { val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) val tensor3 = zeros(intArrayOf(2, 3, 4, 5)) - assertTrue(diagonalEmbedding(tensor3, 0, 3, 4).shape contentEquals - intArrayOf(2, 3, 4, 5, 5)) - assertTrue(diagonalEmbedding(tensor3, 1, 3, 4).shape contentEquals - intArrayOf(2, 3, 4, 6, 6)) - assertTrue(diagonalEmbedding(tensor3, 2, 0, 3).shape contentEquals - intArrayOf(7, 2, 3, 7, 4)) + assertTrue( + diagonalEmbedding(tensor3, 0, 3, 4).shape contentEquals + intArrayOf(2, 3, 4, 5, 5) + ) + assertTrue( + diagonalEmbedding(tensor3, 1, 3, 4).shape contentEquals + intArrayOf(2, 3, 4, 6, 6) + ) + assertTrue( + diagonalEmbedding(tensor3, 2, 0, 3).shape contentEquals + intArrayOf(7, 2, 3, 7, 4) + ) val diagonal1 = diagonalEmbedding(tensor1, 0, 1, 0) assertTrue(diagonal1.shape contentEquals intArrayOf(3, 3)) - assertTrue(diagonal1.mutableBuffer.array() contentEquals - doubleArrayOf(10.0, 0.0, 0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 30.0)) + assertTrue( + diagonal1.source contentEquals + doubleArrayOf(10.0, 0.0, 0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 30.0) + ) val diagonal1Offset = diagonalEmbedding(tensor1, 1, 1, 0) assertTrue(diagonal1Offset.shape contentEquals intArrayOf(4, 4)) - assertTrue(diagonal1Offset.mutableBuffer.array() contentEquals - doubleArrayOf(0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 30.0, 0.0)) + assertTrue( + diagonal1Offset.source contentEquals + doubleArrayOf(0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 30.0, 0.0) + ) val diagonal2 = diagonalEmbedding(tensor2, 1, 0, 2) assertTrue(diagonal2.shape contentEquals intArrayOf(4, 2, 4)) - assertTrue(diagonal2.mutableBuffer.array() contentEquals - doubleArrayOf( - 0.0, 1.0, 0.0, 0.0, 0.0, 4.0, 0.0, 0.0, - 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 5.0, 0.0, - 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 6.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)) + assertTrue( + diagonal2.source contentEquals + doubleArrayOf( + 0.0, 1.0, 0.0, 0.0, 0.0, 4.0, 0.0, 0.0, + 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 5.0, 0.0, + 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 6.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + ) + ) } @Test @@ -178,4 +194,14 @@ internal class TestDoubleTensorAlgebra { assertFalse(tensor1.eq(tensor3)) } + + @Test + fun testMap() = DoubleTensorAlgebra { + val tensor = one(5, 5, 5) + val l = tensor.getTensor(0).map { it + 1.0 } + val r = tensor.getTensor(1).map { it - 1.0 } + val res = l + r + assertTrue { intArrayOf(5, 5) contentEquals res.shape } + assertEquals(1.0, res[4, 4]) + } } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/offsetBufferEquality.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/offsetBufferEquality.kt new file mode 100644 index 000000000..e9fc7fb9c --- /dev/null +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/offsetBufferEquality.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2018-2022 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.tensors.core + +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.DoubleBuffer +import space.kscience.kmath.structures.indices +import kotlin.jvm.JvmName + + +/** + * Simplified [DoubleBuffer] to array comparison + */ +public fun OffsetDoubleBuffer.contentEquals(vararg doubles: Double): Boolean = indices.all { get(it) == doubles[it] } + +@JvmName("contentEqualsArray") +public infix fun OffsetDoubleBuffer.contentEquals(otherArray: DoubleArray): Boolean = contentEquals(*otherArray) + +@JvmName("contentEqualsBuffer") +public infix fun OffsetDoubleBuffer.contentEquals(otherBuffer: Buffer): Boolean = + indices.all { get(it) == otherBuffer[it] } \ No newline at end of file diff --git a/test-utils/src/commonMain/kotlin/bufferEquality.kt b/test-utils/src/commonMain/kotlin/bufferEquality.kt new file mode 100644 index 000000000..9e4d9ec22 --- /dev/null +++ b/test-utils/src/commonMain/kotlin/bufferEquality.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2018-2022 KMath contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package space.kscience.kmath.testutils + +import space.kscience.kmath.structures.DoubleBuffer +import kotlin.jvm.JvmName + +/** + * Simplified [DoubleBuffer] to array comparison + */ +public fun DoubleBuffer.contentEquals(vararg doubles: Double): Boolean = array.contentEquals(doubles) + +@JvmName("contentEqualsArray") +public infix fun DoubleBuffer.contentEquals(otherArray: DoubleArray): Boolean = array.contentEquals(otherArray) + +@JvmName("contentEqualsBuffer") +public infix fun DoubleBuffer.contentEquals(otherBuffer: DoubleBuffer): Boolean = array.contentEquals(otherBuffer.array) \ No newline at end of file -- 2.34.1 From 20886d6f6b366047e7d80cee76030f5413e60ed0 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 11 Sep 2022 17:10:26 +0300 Subject: [PATCH 181/275] Global refactor of tensors --- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 7 +++-- .../kmath/tensors/core/IntTensorAlgebra.kt | 5 ++-- .../tensors/core/TensorLinearStructure.kt | 8 +++--- .../core/internal/doubleTensorHelpers.kt | 27 +++++++++---------- .../tensors/core/internal/intTensorHelpers.kt | 2 +- .../kmath/tensors/core/tensorTransform.kt | 17 +++++++++--- .../kmath/tensors/core/TestDoubleTensor.kt | 23 +++++++--------- .../tensors/core/TestDoubleTensorAlgebra.kt | 7 ++--- 8 files changed, 52 insertions(+), 44 deletions(-) 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 d758c49a1..f563d00ae 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/DoubleTensorAlgebra.kt @@ -132,7 +132,10 @@ public open class DoubleTensorAlgebra : val dt = asDoubleTensor() val lastShape = shape.drop(1).toIntArray() val newShape = if (lastShape.isNotEmpty()) lastShape else intArrayOf(1) - return DoubleTensor(newShape, dt.source.view(newShape.reduce(Int::times) * i)) + return DoubleTensor( + newShape, + dt.source.view(newShape.reduce(Int::times) * i, TensorLinearStructure.linearSizeOf(newShape)) + ) } /** @@ -227,7 +230,7 @@ public open class DoubleTensorAlgebra : override fun StructureND.minus(arg: Double): DoubleTensor = map { it - arg } - override fun StructureND.minus(arg: StructureND): DoubleTensor = zip(this, arg) { l, r -> l + r } + override fun StructureND.minus(arg: StructureND): DoubleTensor = zip(this, arg) { l, r -> l - r } override fun Tensor.minusAssign(value: Double) { mapInPlace { it - 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 7c18fe533..124ccc668 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 @@ -221,7 +221,7 @@ public open class IntTensorAlgebra : TensorAlgebra { override fun StructureND.minus(arg: Int): IntTensor = map { it - arg } - override fun StructureND.minus(arg: StructureND): IntTensor = zip(this, arg) { l, r -> l + r } + override fun StructureND.minus(arg: StructureND): IntTensor = zip(this, arg) { l, r -> l - r } override fun Tensor.minusAssign(value: Int) { mapInPlace { it - value } @@ -283,8 +283,7 @@ public open class IntTensorAlgebra : TensorAlgebra { view(other.shape) override fun StructureND.dot(other: StructureND): IntTensor { - return if (dimension in 0..2 && other.dimension in 0..2) TODO("not implemented") - else error("Only vectors and matrices are allowed in non-broadcasting dot operation") + TODO("not implemented for integers") } override fun diagonalEmbedding( diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt index 3de1c9b1a..729fc0d13 100644 --- a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/TensorLinearStructure.kt @@ -15,14 +15,12 @@ import kotlin.math.max * @param shape the shape of the tensor. */ public class TensorLinearStructure(override val shape: IntArray) : Strides() { - override val strides: IntArray - get() = stridesFromShape(shape) + override val strides: IntArray get() = stridesFromShape(shape) override fun index(offset: Int): IntArray = indexFromOffset(offset, strides, shape.size) - override val linearSize: Int - get() = shape.reduce(Int::times) + override val linearSize: Int get() = linearSizeOf(shape) override fun equals(other: Any?): Boolean { if (this === other) return true @@ -41,6 +39,8 @@ public class TensorLinearStructure(override val shape: IntArray) : Strides() { public companion object { + public fun linearSizeOf(shape: IntArray): Int = shape.reduce(Int::times) + public fun stridesFromShape(shape: IntArray): IntArray { val nDim = shape.size val res = IntArray(nDim) diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/doubleTensorHelpers.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/doubleTensorHelpers.kt index 9c6f54d61..c5910a436 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 @@ -14,11 +14,8 @@ 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 @@ -165,7 +162,7 @@ internal val DoubleTensor.vectors: VirtualBuffer return VirtualBuffer(linearSize / vectorOffset) { index -> val offset = index * vectorOffset - DoubleTensor(vectorShape, source.view(offset)) + DoubleTensor(vectorShape, source.view(offset, vectorShape.first())) } } @@ -174,16 +171,18 @@ internal fun DoubleTensor.vectorSequence(): Sequence = vectors.asS internal val DoubleTensor.matrices: VirtualBuffer - get(){ - val n = shape.size - check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n" } - val matrixOffset = shape[n - 1] * shape[n - 2] - val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) + get() { + val n = shape.size + check(n >= 2) { "Expected tensor with 2 or more dimensions, got size $n" } + val matrixOffset = shape[n - 1] * shape[n - 2] + val matrixShape = intArrayOf(shape[n - 2], shape[n - 1]) - return VirtualBuffer(linearSize / matrixOffset) { index -> - val offset = index * matrixOffset - DoubleTensor(matrixShape, source.view(offset)) + val size = TensorLinearStructure.linearSizeOf(matrixShape) + + return VirtualBuffer(linearSize / matrixOffset) { index -> + val offset = index * matrixOffset + DoubleTensor(matrixShape, source.view(offset, size)) + } } -} internal fun DoubleTensor.matrixSequence(): Sequence = matrices.asSequence() \ No newline at end of file diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/intTensorHelpers.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/internal/intTensorHelpers.kt index 93229c2d4..db289a090 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 @@ -40,7 +40,7 @@ internal val IntTensor.vectors: VirtualBuffer return VirtualBuffer(linearSize / vectorOffset) { index -> val offset = index * vectorOffset - IntTensor(vectorShape, source.view(offset)) + IntTensor(vectorShape, source.view(offset, vectorShape.first())) } } 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 30a828d6a..118624440 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,14 +5,20 @@ package space.kscience.kmath.tensors.core +import space.kscience.kmath.nd.DoubleBufferND import space.kscience.kmath.nd.StructureND import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.asBuffer import space.kscience.kmath.tensors.api.Tensor +/** + * Create a mutable copy of given [StructureND]. + */ public fun StructureND.copyToTensor(): DoubleTensor = if (this is DoubleTensor) { DoubleTensor(shape, source.copy()) +} else if (this is DoubleBufferND && indices is TensorLinearStructure) { + DoubleTensor(shape, buffer.copy()) } else { DoubleTensor( shape, @@ -36,11 +42,14 @@ public fun StructureND.toDoubleTensor(): DoubleTensor { } /** - * Casts [Tensor] of [Double] to [DoubleTensor] + * Transforms [StructureND] of [Double] to [DoubleTensor]. Zero copy if possible, but is not guaranteed */ -public fun StructureND.asDoubleTensor(): DoubleTensor = when (this) { - is DoubleTensor -> this - else -> copyToTensor() +public fun StructureND.asDoubleTensor(): DoubleTensor = if (this is DoubleTensor) { + this +} else if (this is DoubleBufferND && indices is TensorLinearStructure) { + DoubleTensor(shape, buffer) +} else { + copyToTensor() } /** 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 a36f32ac9..c87cf2a68 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensor.kt @@ -6,10 +6,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.nd.DefaultStrides -import space.kscience.kmath.nd.MutableBufferND -import space.kscience.kmath.nd.as1D -import space.kscience.kmath.nd.as2D +import space.kscience.kmath.nd.* import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.toDoubleArray @@ -66,16 +63,16 @@ internal class TestDoubleTensor { fun testNoBufferProtocol() { // create buffer - val doubleArray = DoubleBuffer(doubleArrayOf(1.0, 2.0, 3.0)) + val doubleArray = DoubleBuffer(1.0, 2.0, 3.0) // create ND buffers, no data is copied - val ndArray: MutableBufferND = MutableBufferND(DefaultStrides(intArrayOf(3)), doubleArray) + val ndArray: MutableBufferND = DoubleBufferND(DefaultStrides(intArrayOf(3)), doubleArray) // map to tensors - val bufferedTensorArray = ndArray.asDoubleTensor() // strides are flipped so data copied - val tensorArray = bufferedTensorArray.asDoubleTensor() // data not contiguous so copied again + val tensorArray = ndArray.asDoubleTensor() // Data is copied because of strides change. - val tensorArrayPublic = ndArray.asDoubleTensor() // public API, data copied twice + //protective copy + val tensorArrayPublic = ndArray.copyToTensor() // public API, data copied twice val sharedTensorArray = tensorArrayPublic.asDoubleTensor() // no data copied by matching type assertTrue(tensorArray.source contentEquals sharedTensorArray.source) @@ -83,11 +80,11 @@ internal class TestDoubleTensor { tensorArray[intArrayOf(0)] = 55.9 assertEquals(tensorArrayPublic[intArrayOf(0)], 1.0) - tensorArrayPublic[intArrayOf(0)] = 55.9 - assertEquals(sharedTensorArray[intArrayOf(0)], 55.9) - assertEquals(bufferedTensorArray[intArrayOf(0)], 1.0) + tensorArrayPublic[intArrayOf(0)] = 57.9 + assertEquals(sharedTensorArray[intArrayOf(0)], 57.9) + assertEquals(tensorArray[intArrayOf(0)], 55.9) - bufferedTensorArray[intArrayOf(0)] = 55.9 + tensorArray[intArrayOf(0)] = 55.9 assertEquals(ndArray[intArrayOf(0)], 1.0) } diff --git a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt index 79b199471..67bebb9a7 100644 --- a/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt +++ b/kmath-tensors/src/commonTest/kotlin/space/kscience/kmath/tensors/core/TestDoubleTensorAlgebra.kt @@ -8,6 +8,7 @@ package space.kscience.kmath.tensors.core import space.kscience.kmath.nd.get import space.kscience.kmath.operations.invoke +import space.kscience.kmath.testutils.assertBufferEquals import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFalse @@ -98,8 +99,8 @@ internal class TestDoubleTensorAlgebra { assignResult += tensorC assignResult += -39.4 - assertTrue(expected.source contentEquals result.source) - assertTrue(expected.source contentEquals assignResult.source) + assertBufferEquals(expected.source, result.source) + assertBufferEquals(expected.source, assignResult.source) } @Test @@ -202,6 +203,6 @@ internal class TestDoubleTensorAlgebra { val r = tensor.getTensor(1).map { it - 1.0 } val res = l + r assertTrue { intArrayOf(5, 5) contentEquals res.shape } - assertEquals(1.0, res[4, 4]) + assertEquals(2.0, res[4, 4]) } } -- 2.34.1 From 2358f53cf7ae26220d0f7ae5bc99c8b54942d89b Mon Sep 17 00:00:00 2001 From: darksnake Date: Thu, 15 Sep 2022 17:42:37 +0300 Subject: [PATCH 182/275] Make Circle2D data class --- .../commonMain/kotlin/space/kscience/kmath/geometry/Circle2D.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 5a25fef7d..162130908 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 @@ -10,7 +10,7 @@ import kotlin.math.PI /** * A circle in 2D space */ -public class Circle2D( +public data class Circle2D( public val center: DoubleVector2D, public val radius: Double ) -- 2.34.1 From 6bf8d9d325d6a04e74c2b776cc8f7025729a5f94 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 26 Sep 2022 13:08:49 +0300 Subject: [PATCH 183/275] 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()) } } -- 2.34.1 From d70389d2e622c93fa5ffb0f828428ae5261ab1f9 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 26 Sep 2022 16:47:38 +0300 Subject: [PATCH 184/275] 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 185/275] 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) -- 2.34.1 From 89d0cbc7ea92bdace8920ce401c30825d48d5949 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 30 Sep 2022 11:34:44 +0300 Subject: [PATCH 186/275] 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) + } } } -- 2.34.1 From b0abcf2d0c0d468f927dffe277e525e7cf678847 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 14 Oct 2022 12:47:57 +0300 Subject: [PATCH 187/275] 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) } -- 2.34.1 From ee569b85f801972fd7cbd44d43abcd1df0a1b30d Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 14 Oct 2022 13:05:39 +0300 Subject: [PATCH 188/275] 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) -- 2.34.1 From e24463c58bc6368709c2db681f9d1b8518f36f7d Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 15 Oct 2022 18:45:06 +0300 Subject: [PATCH 189/275] 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()) } } -- 2.34.1 From fb0d016aa824227b2b76f102525584426ad1e48a Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 15 Oct 2022 18:58:30 +0300 Subject: [PATCH 190/275] 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 -- 2.34.1 From 94489b28e254f0f3c5c95c1b8a63588e3a390838 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 16 Oct 2022 14:41:48 +0300 Subject: [PATCH 191/275] 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 -- 2.34.1 From 8286db30afef0fb5e647117fd7892f20ebfc1e73 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 16 Oct 2022 20:15:37 +0300 Subject: [PATCH 192/275] 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 -- 2.34.1 From cff563c321fba4c5fe9be3660d504079acfdc746 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 5 Nov 2022 16:14:23 +0300 Subject: [PATCH 193/275] 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( -- 2.34.1 From b14e2fdd083e26a7843e75ec35a0a5c5118a2d53 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 5 Nov 2022 21:44:41 +0300 Subject: [PATCH 194/275] 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", -- 2.34.1 From 991ab907d87536c636f2ab6830a0f4a28886c386 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 10 Dec 2022 11:09:55 +0300 Subject: [PATCH 195/275] 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. -- 2.34.1 From 29977650f10d0d1168a4f218b2b71e371b567653 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 10 Dec 2022 12:21:56 +0300 Subject: [PATCH 196/275] 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 +} -- 2.34.1 From 6d47c0ccecd4068cc4c6289741d5dc89931c4a13 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 10 Dec 2022 12:30:15 +0300 Subject: [PATCH 197/275] 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 } } -- 2.34.1 From 3f4fe9e43ba488b5d5de65aaf9b916159023724e Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 31 Dec 2022 15:02:52 +0300 Subject: [PATCH 198/275] 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") } } -- 2.34.1 From 2e4be2aa3a3678ee5fed7de029106bb793ed4c32 Mon Sep 17 00:00:00 2001 From: darksnake Date: Tue, 24 Jan 2023 11:36:53 +0300 Subject: [PATCH 199/275] 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 -- 2.34.1 From 7f4f4c7703275e80cb51e38af3a28a7672dbbf5f Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 24 Jan 2023 21:01:26 +0300 Subject: [PATCH 200/275] 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 -- 2.34.1 From d97888f1350250e07d8c186714d58e05484a06a5 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 24 Jan 2023 21:22:25 +0300 Subject: [PATCH 201/275] 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 -- 2.34.1 From db3091354225a8a054de7acc281216ef7f569d04 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 3 Feb 2023 19:32:53 +0300 Subject: [PATCH 202/275] 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() } -- 2.34.1 From 0366a69123fc45690d5b6983d83a3c90929d1084 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 3 Feb 2023 19:33:22 +0300 Subject: [PATCH 203/275] 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))) } } } -- 2.34.1 From 2c6d1e89c512627f79c579e7305197d3a3ae98db Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 5 Feb 2023 20:05:53 +0300 Subject: [PATCH 204/275] 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) } } -- 2.34.1 From 6deeaf057e64d0ccaba0abb3cab32c64a8e76455 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 11 Feb 2023 21:51:19 +0300 Subject: [PATCH 205/275] 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 -- 2.34.1 From 784d397ab12103bae441d770b8ee6c2f8e0c03c3 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 12 Feb 2023 10:40:53 +0300 Subject: [PATCH 206/275] 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 } } -- 2.34.1 From 50579f4712695629d477eb1031f1a36e0d34f9af Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Mon, 13 Feb 2023 23:17:13 +0300 Subject: [PATCH 207/275] 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 -- 2.34.1 From bef317677c9a1c3496595dca8999a06ead1c3f85 Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Wed, 15 Feb 2023 14:36:58 +0300 Subject: [PATCH 208/275] 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 -- 2.34.1 From d535a2155f3171b538a2f6019dffad9ef83f2001 Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Wed, 15 Feb 2023 15:06:47 +0300 Subject: [PATCH 209/275] 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)), -- 2.34.1 From c342c5cd7835c92a7ccd26d07872b8018f7980f2 Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Wed, 15 Feb 2023 17:53:32 +0300 Subject: [PATCH 210/275] 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 -- 2.34.1 From 8998a394b34e6946f820d27521b40cd67ba3a33f Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Wed, 15 Feb 2023 17:55:39 +0300 Subject: [PATCH 211/275] 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 -- 2.34.1 From 7d897ad8cb6758b57d9bc08d3ec7250caae944dc Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 16 Feb 2023 10:29:12 +0300 Subject: [PATCH 212/275] 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 -- 2.34.1 From 67316c4a70cee2814ef2e65dece45077bef7c894 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 16 Feb 2023 10:39:25 +0300 Subject: [PATCH 213/275] 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) { -- 2.34.1 From ed4aa47913c2cc982e9a325e3635774d00d01dec Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 16 Feb 2023 10:57:24 +0300 Subject: [PATCH 214/275] 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) } } -- 2.34.1 From cc0fb2a718a3981332328b75ce2a86b4610b161d Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Thu, 16 Feb 2023 18:47:42 +0300 Subject: [PATCH 215/275] 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 -- 2.34.1 From 04127fc3f2b781a2e66b95b8b2d63629dca15220 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 18 Feb 2023 18:53:03 +0300 Subject: [PATCH 216/275] 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) } } -- 2.34.1 From db61f7144089056ae184fd1b28c1dd0db2c5fd6f Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 18 Feb 2023 19:04:07 +0300 Subject: [PATCH 217/275] 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 -- 2.34.1 From 2c13386646a6f3f38523e9546eccf38343251163 Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Wed, 1 Mar 2023 10:40:54 +0300 Subject: [PATCH 218/275] 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") } } } -- 2.34.1 From 61d43ae5faa05f8c9d90d6519897a7f0ebd6b77a Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Sat, 4 Mar 2023 21:31:06 +0300 Subject: [PATCH 219/275] 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 -- 2.34.1 From 1b6a41c728150bb9374625b06045c06f8073c524 Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Thu, 9 Mar 2023 08:39:20 +0300 Subject: [PATCH 220/275] 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 -- 2.34.1 From 2bce369c5dcdae8b4ba16f498fd19d31807b29df Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Thu, 9 Mar 2023 16:03:48 +0300 Subject: [PATCH 221/275] 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() { -- 2.34.1 From 4871baf0e5f4d45bf3c7d31916d4b84be187b689 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 10 Mar 2023 12:01:08 +0300 Subject: [PATCH 222/275] 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) + } + } -- 2.34.1 From a3963ac4f50b7042cf21c51c8b5f97c36877249e Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 10 Mar 2023 21:40:14 +0300 Subject: [PATCH 223/275] 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 -- 2.34.1 From 72c70302974a1cc568f32a6c6242d7180c77a9fd Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 10 Mar 2023 22:50:41 +0300 Subject: [PATCH 224/275] 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 { -- 2.34.1 From 4c1ffdb6d9db3ea37ff159ad95958184bb8fd517 Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Tue, 14 Mar 2023 13:50:42 +0300 Subject: [PATCH 225/275] 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 -- 2.34.1 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 226/275] 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) -- 2.34.1 From cd2ade881add23d4ac9b3f4b4d5ea594b6ad6d63 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 16 Mar 2023 09:33:17 +0300 Subject: [PATCH 227/275] 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) -- 2.34.1 From ef336af87ddb6df9acc8029e9633234ae5fe6851 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 16 Mar 2023 09:37:03 +0300 Subject: [PATCH 228/275] 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 -- 2.34.1 From c36af3515e08adb3595a95a6470309eb149fc0c9 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 19 Mar 2023 18:39:27 +0300 Subject: [PATCH 229/275] 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")) } -- 2.34.1 From 62c8610a9ebb45d5c450ef283ce21ec5e0d4de3c Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 19 Mar 2023 19:16:46 +0300 Subject: [PATCH 230/275] 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 }} -- 2.34.1 From c442eb7e94ff562688b171cfcdf7deb829b71d47 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 19 Mar 2023 19:41:31 +0300 Subject: [PATCH 231/275] 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 }} -- 2.34.1 From 81213eb94340fc87ae6958d30e598d234439dc35 Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Tue, 21 Mar 2023 12:04:27 +0300 Subject: [PATCH 232/275] 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) -- 2.34.1 From 56bba749c026863a02ed6eb461d85d29d56e81e6 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 22 Mar 2023 10:54:24 +0300 Subject: [PATCH 233/275] 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) -- 2.34.1 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 234/275] 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 -- 2.34.1 From ea5305c8d878e910128543f44453fe7e20294164 Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Fri, 24 Mar 2023 10:28:02 +0300 Subject: [PATCH 235/275] 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 -- 2.34.1 From 24c39c97cd4b9186a8445dedffff4c7fcc3e5ca1 Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Fri, 24 Mar 2023 10:30:13 +0300 Subject: [PATCH 236/275] 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)) -- 2.34.1 From 11dd4088d977f5c2ecacfe264e77bf432a44a8e3 Mon Sep 17 00:00:00 2001 From: Artyom Degtyarev Date: Fri, 24 Mar 2023 10:39:51 +0300 Subject: [PATCH 237/275] 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() { -- 2.34.1 From f809e40791f73ab33bb05d3a23947fe8af310f98 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 4 Apr 2023 11:42:58 +0300 Subject: [PATCH 238/275] 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) -- 2.34.1 From 109e050f03abc0b585a024dd8abd743aa434e8d1 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 4 Apr 2023 15:16:33 +0300 Subject: [PATCH 239/275] 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) -- 2.34.1 From fd35d7c6143a5f544788bfda005cc399dc3cb245 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 4 Apr 2023 15:28:02 +0300 Subject: [PATCH 240/275] [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 ) ) -- 2.34.1 From 1e46ffbd98809c43b14c5b8f4df65f9315d040c7 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 4 Apr 2023 16:50:30 +0300 Subject: [PATCH 241/275] 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() } -- 2.34.1 From f5201b6be0c2cf784e2a192193d2f7130caac857 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 4 Apr 2023 17:42:40 +0300 Subject: [PATCH 242/275] 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) } } -- 2.34.1 From 639a255aaf96c3b41a458774036b3f48efd86765 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 4 Apr 2023 18:50:17 +0300 Subject: [PATCH 243/275] 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 ) -- 2.34.1 From 025cb5806030665550f0767bc7de8ecec7ad3c7a Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 4 Apr 2023 19:02:24 +0300 Subject: [PATCH 244/275] 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 ) -- 2.34.1 From a0e2ef1afc08765240f0e00ac39205a25bdc92e8 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 4 Apr 2023 19:33:43 +0300 Subject: [PATCH 245/275] 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 -- 2.34.1 From 00ce7d5a48e4736ec6d80a480327a2c550787425 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 5 Apr 2023 13:30:13 +0300 Subject: [PATCH 246/275] 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) ) } -- 2.34.1 From 7cc6a4be400bb7195dba6df50259a2c48cee849f Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 5 Apr 2023 15:26:09 +0300 Subject: [PATCH 247/275] 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", ) -- 2.34.1 From 1d7f4ed538efcbafe5527d5e26635f160d3a003a Mon Sep 17 00:00:00 2001 From: mrFendel Date: Thu, 6 Apr 2023 03:17:01 +0300 Subject: [PATCH 248/275] shiftOp and diff in SeriesAlgebra --- .../kscience/kmath/series/SeriesAlgebra.kt | 36 ++++++++++++++++++- 1 file changed, 35 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 3cd2212f6..bdd74c4fe 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 @@ -3,16 +3,21 @@ package space.kscience.kmath.series import space.kscience.kmath.operations.BufferAlgebra import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.RingOps +import space.kscience.kmath.operations.reduce import space.kscience.kmath.stat.StatisticalAlgebra import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.BufferView import kotlin.math.max import kotlin.math.min + +// TODO: check if ranges are intersected @PublishedApi internal fun IntRange.intersect(other: IntRange): IntRange = max(first, other.first)..min(last, other.last) + @PublishedApi internal val IntRange.size: Int get() = last - first + 1 @@ -33,11 +38,14 @@ 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 */ + private class SeriesImpl( override val origin: Buffer, override val position: Int, @@ -107,6 +115,8 @@ public class SeriesAlgebra, out BA : BufferAlgebra, L>( * Get a label buffer for given buffer. */ public val Buffer.labels: List get() = indices.map(labelResolver) + // TODO: there can be troubles with label consistency after moving position argument + // TODO: so offset should be reflected in the labelResolver also /** @@ -145,6 +155,17 @@ public class SeriesAlgebra, out BA : BufferAlgebra, L>( return accumulator } + // TODO: add fold with recorded accumulation +// public inline fun Buffer.traceFold(initial: R, operation: A.(acc: R, T) -> R): Buffer { +// var tempBuffer = elementAlgebra.bufferFactory(this.size) {i -> getAbsolute(i)} +// var accumulator = initial +// for (index in this.indices) { +// accumulator = elementAlgebra.operation(accumulator, getAbsolute(index)) +// tempBuffer.set(index, accumulator) +// } +// return elementAlgebra.bufferFactory(this.size) {i -> tempBuffer.getAbsolute(i)} +// } + public inline fun Buffer.foldWithLabel(initial: R, operation: A.(acc: R, arg: T, label: L) -> R): R { val labels = labels var accumulator = initial @@ -154,7 +175,7 @@ public class SeriesAlgebra, out BA : BufferAlgebra, L>( } /** - * Zip two buffers in the range whe they overlap + * Zip two buffers in the range where they overlap */ public inline fun Buffer.zip( other: Buffer, @@ -169,11 +190,24 @@ public class SeriesAlgebra, out BA : BufferAlgebra, L>( }.moveTo(newRange.first) } + /** + * Zip buffer with itself, but shifted + * */ + public inline fun Buffer.shiftOp( + shift: Int = 1, + crossinline operation: A.(left: T, right: T) -> T + ): Buffer { + val shifted = this.moveTo(this.offset+shift) + return zip(shifted, operation) + } + 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 inline fun Buffer.diff(): Buffer = this.shiftOp {l, r -> r - l} } public fun , BA : BufferAlgebra, L> BA.seriesAlgebra(labels: Iterable): SeriesAlgebra { -- 2.34.1 From ba26c7020e76a5b2384f37d515471f287a37617c Mon Sep 17 00:00:00 2001 From: mrFendel Date: Thu, 6 Apr 2023 17:58:29 +0300 Subject: [PATCH 249/275] started TimeSeriesAlgebra --- .../kscience/kmath/series/SeriesAlgebra.kt | 11 ------ .../kmath/series/TimeSeriesAlgebra.kt | 37 +++++++++++++++++++ 2 files changed, 37 insertions(+), 11 deletions(-) create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/TimeSeriesAlgebra.kt 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 bdd74c4fe..b6d952955 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 @@ -155,17 +155,6 @@ public class SeriesAlgebra, out BA : BufferAlgebra, L>( return accumulator } - // TODO: add fold with recorded accumulation -// public inline fun Buffer.traceFold(initial: R, operation: A.(acc: R, T) -> R): Buffer { -// var tempBuffer = elementAlgebra.bufferFactory(this.size) {i -> getAbsolute(i)} -// var accumulator = initial -// for (index in this.indices) { -// accumulator = elementAlgebra.operation(accumulator, getAbsolute(index)) -// tempBuffer.set(index, accumulator) -// } -// return elementAlgebra.bufferFactory(this.size) {i -> tempBuffer.getAbsolute(i)} -// } - public inline fun Buffer.foldWithLabel(initial: R, operation: A.(acc: R, arg: T, label: L) -> R): R { val labels = labels var accumulator = initial diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/TimeSeriesAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/TimeSeriesAlgebra.kt new file mode 100644 index 000000000..37abe710e --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/TimeSeriesAlgebra.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. + */ + +package space.kscience.kmath.series + +import space.kscience.kmath.structures.Buffer + + + +public interface TimeSeries: Series { + public override val origin: Buffer + public override val position: Int + + // TODO: Specify the types of DateTime that can be contained in timeStamp Buffer + public val timeStamp: Buffer // Buffer of some datetime instances like: Instant, LocalDate, LocalTime... +} + +private class TimeSeriesImpl( + override val origin: Buffer, + override val timeStamp: Buffer, + override val position: Int, + override val size: Int = origin.size, +) : TimeSeries by origin { // TODO: manage with delegation + + init { + require(size > 0) { "Size must be positive" } + require(size <= origin.size) { "Slice size is larger than the original buffer" } + require(size <= timeStamp.size) { "Slice size is larger than the timeStamp buffer" } + } + +// override fun toString(): String = "$origin-->${position}" +} + + +// TODO: add conversion to Buffer of Pairs ? -- 2.34.1 From 4db091d8984d269cc8abb08dc369277ef78bb942 Mon Sep 17 00:00:00 2001 From: mrFendel Date: Fri, 7 Apr 2023 12:39:30 +0300 Subject: [PATCH 250/275] deleted TimeSeriesAlgebra --- .../kmath/series/TimeSeriesAlgebra.kt | 37 ------------------- 1 file changed, 37 deletions(-) delete mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/TimeSeriesAlgebra.kt diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/TimeSeriesAlgebra.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/TimeSeriesAlgebra.kt deleted file mode 100644 index 37abe710e..000000000 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/TimeSeriesAlgebra.kt +++ /dev/null @@ -1,37 +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.series - -import space.kscience.kmath.structures.Buffer - - - -public interface TimeSeries: Series { - public override val origin: Buffer - public override val position: Int - - // TODO: Specify the types of DateTime that can be contained in timeStamp Buffer - public val timeStamp: Buffer // Buffer of some datetime instances like: Instant, LocalDate, LocalTime... -} - -private class TimeSeriesImpl( - override val origin: Buffer, - override val timeStamp: Buffer, - override val position: Int, - override val size: Int = origin.size, -) : TimeSeries by origin { // TODO: manage with delegation - - init { - require(size > 0) { "Size must be positive" } - require(size <= origin.size) { "Slice size is larger than the original buffer" } - require(size <= timeStamp.size) { "Slice size is larger than the timeStamp buffer" } - } - -// override fun toString(): String = "$origin-->${position}" -} - - -// TODO: add conversion to Buffer of Pairs ? -- 2.34.1 From ce388fed44205fa813028facb29eee0ef3cc59c6 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 7 Apr 2023 19:55:34 +0300 Subject: [PATCH 251/275] Move annotations to base package. Fix series --- CHANGELOG.md | 1 + README.md | 29 +------- .../ExpressionsInterpretersBenchmark.kt | 3 +- .../kmath/benchmarks/BigIntBenchmark.kt | 2 +- .../kmath/benchmarks/NDFieldBenchmark.kt | 2 +- build.gradle.kts | 2 +- .../kmath/ejml/codegen/ejmlCodegen.kt | 2 +- .../kmath/{stat => series}/DateTimeSeries.kt | 4 +- .../space/kscience/kmath/series/analyzeDif.kt | 55 +++++++++------- .../kmath/structures/StreamDoubleFieldND.kt | 2 +- .../structures/StructureReadBenchmark.kt | 2 +- kmath-ast/README.md | 6 +- .../space/kscience/kmath/ast/TypedMst.kt | 2 +- .../kscience/kmath/ast/evaluateConstants.kt | 2 +- .../ast/rendering/LatexSyntaxRenderer.kt | 2 +- .../ast/rendering/MathMLSyntaxRenderer.kt | 2 +- .../kmath/ast/rendering/MathRenderer.kt | 2 +- .../kmath/ast/rendering/MathSyntax.kt | 2 +- .../kmath/ast/rendering/SyntaxRenderer.kt | 2 +- .../kscience/kmath/ast/rendering/features.kt | 2 +- .../kscience/kmath/ast/rendering/phases.kt | 2 +- .../space/kscience/kmath/estree/estree.kt | 2 +- .../kmath/wasm/internal/WasmBuilder.kt | 2 +- .../kotlin/space/kscience/kmath/wasm/wasm.kt | 2 +- .../kotlin/space/kscience/kmath/asm/asm.kt | 2 +- .../kmath/asm/internal/PrimitiveAsmBuilder.kt | 2 +- kmath-commons/README.md | 6 +- .../commons/expressions/CmDsExpression.kt | 2 +- .../kmath/commons/integration/CMIntegrator.kt | 2 +- .../kscience/kmath/commons/linear/CMMatrix.kt | 2 +- .../kmath/commons/optimization/CMOptimizer.kt | 2 +- .../commons/integration/IntegrationTest.kt | 2 +- .../commons/optimization/OptimizeTest.kt | 2 +- kmath-complex/README.md | 6 +- .../space/kscience/kmath/complex/Complex.kt | 2 +- .../kscience/kmath/complex/ComplexFieldND.kt | 4 +- .../kscience/kmath/complex/Quaternion.kt | 2 +- kmath-core/README.md | 6 +- kmath-core/build.gradle.kts | 1 + .../space/kscience/kmath/data/ColumnarData.kt | 4 +- .../kscience/kmath/data/XYColumnarData.kt | 4 +- .../kmath/data/XYErrorColumnarData.kt | 2 +- .../kscience/kmath/data/XYZColumnarData.kt | 2 +- .../space/kscience/kmath/domains/Domain1D.kt | 2 +- .../kscience/kmath/domains/DoubleDomain.kt | 2 +- .../kmath/domains/HyperSquareDomain.kt | 2 +- .../kmath/domains/UnconstrainedDomain.kt | 2 +- .../kscience/kmath/expressions/DSAlgebra.kt | 2 +- .../kscience/kmath/expressions/Expression.kt | 2 +- .../kscience/kmath/expressions/MstAlgebra.kt | 2 +- .../kscience/kmath/expressions/NamedMatrix.kt | 4 +- .../kmath/expressions/SimpleAutoDiff.kt | 2 +- .../kmath/expressions/SymbolIndexer.kt | 2 +- .../kmath/linear/BufferedLinearSpace.kt | 2 +- .../kmath/linear/DoubleLinearSpace.kt | 2 +- .../kscience/kmath/linear/LinearSpace.kt | 2 +- .../kscience/kmath/linear/LupDecomposition.kt | 2 +- .../kscience/kmath/linear/MatrixBuilder.kt | 2 +- .../kscience/kmath/linear/MatrixWrapper.kt | 2 +- .../space/kscience/kmath/misc/collections.kt | 2 +- .../space/kscience/kmath/misc/sorting.kt | 1 + .../space/kscience/kmath/nd/AlgebraND.kt | 4 +- .../kscience/kmath/nd/BufferAlgebraND.kt | 4 +- .../space/kscience/kmath/nd/BufferND.kt | 2 +- .../space/kscience/kmath/nd/DoubleFieldND.kt | 4 +- .../space/kscience/kmath/nd/IntRingND.kt | 2 +- .../kscience/kmath/nd/PermutedStructureND.kt | 2 +- .../kotlin/space/kscience/kmath/nd/ShapeND.kt | 2 +- .../space/kscience/kmath/nd/ShortRingND.kt | 2 +- .../space/kscience/kmath/nd/Structure1D.kt | 2 +- .../space/kscience/kmath/nd/Structure2D.kt | 2 +- .../space/kscience/kmath/nd/StructureND.kt | 2 +- .../kscience/kmath/nd/VirtualStructureND.kt | 4 +- .../space/kscience/kmath/nd/operationsND.kt | 2 +- .../kscience/kmath/nd/primitiveStructureND.kt | 2 +- .../kscience/kmath/operations/Algebra.kt | 2 +- .../space/kscience/kmath/operations/BigInt.kt | 2 +- .../kmath/operations/DoubleBufferOps.kt | 5 +- .../kscience/kmath/operations/LogicAlgebra.kt | 2 +- .../kmath/operations/NumericAlgebra.kt | 2 +- .../kmath/operations/algebraExtensions.kt | 2 +- .../kscience/kmath/structures/BufferView.kt | 2 +- .../kscience/kmath/structures/MemoryBuffer.kt | 4 +- .../kmath/structures/bufferExtensions.kt | 2 +- .../kmath/structures/bufferPrimitiveAccess.kt | 2 +- .../kscience/kmath/expressions/DSTest.kt | 2 +- .../kmath/expressions/InterpretTest.kt | 2 +- .../kmath/linear/DoubleLUSolverTest.kt | 4 +- .../space/kscience/kmath/linear/MatrixTest.kt | 4 +- .../kmath/operations/BigIntAlgebraTest.kt | 2 +- .../kmath/structures/NumberNDFieldTest.kt | 9 ++- .../space/kscience/kmath/misc/numbers.kt | 12 ++++ .../kscience/kmath/operations/isInteger.kt | 12 ++++ kmath-coroutines/README.md | 6 +- .../space/kscience/kmath/chains/Chain.kt | 2 +- .../kmath/structures/LazyStructureND.kt | 2 +- kmath-dimensions/README.md | 6 +- kmath-ejml/README.md | 6 +- .../kscience/kmath/ejml/EjmlLinearSpace.kt | 2 +- .../space/kscience/kmath/ejml/_generated.kt | 2 +- .../kscience/kmath/ejml/EjmlMatrixTest.kt | 4 +- kmath-for-real/README.md | 6 +- .../space/kscience/kmath/real/DoubleVector.kt | 2 +- .../space/kscience/kmath/real/RealMatrix.kt | 4 +- .../kotlin/space/kscience/kmath/real/grids.kt | 2 +- .../kscience/kmath/real/DoubleMatrixTest.kt | 4 +- .../space/kscience/kmath/real/GridTest.kt | 6 +- kmath-functions/README.md | 6 +- .../kscience/kmath/functions/Piecewise.kt | 2 +- .../kmath/functions/polynomialUtil.kt | 2 +- .../kmath/integration/GaussIntegrator.kt | 2 +- .../kmath/integration/SimpsonIntegrator.kt | 2 +- .../kmath/integration/SplineIntegrator.kt | 4 +- .../kmath/integration/UnivariateIntegrand.kt | 2 +- .../kmath/interpolation/Interpolator.kt | 2 +- .../kmath/interpolation/LinearInterpolator.kt | 2 +- .../kmath/interpolation/SplineInterpolator.kt | 2 +- .../kmath/functions/PolynomialUtilTest.kt | 2 +- .../kmath/functions/testUtils/Rational.kt | 2 +- .../kmath/integration/GaussIntegralTest.kt | 2 +- .../kmath/integration/SimpsonIntegralTest.kt | 2 +- .../kmath/integration/SplineIntegralTest.kt | 2 +- kmath-geometry/README.md | 6 +- .../kscience/kmath/geometry/rotations3D.kt | 7 +- kmath-histograms/README.md | 6 +- .../kscience/kmath/histogram/Histogram1D.kt | 2 +- .../kscience/kmath/histogram/HistogramND.kt | 2 +- .../kmath/histogram/UniformHistogram1D.kt | 2 +- .../histogram/UniformHistogramGroupND.kt | 4 +- .../histogram/MultivariateHistogramTest.kt | 4 +- .../kmath/histogram/UniformHistogram1DTest.kt | 2 +- .../kmath/histogram/TreeHistogramGroup.kt | 2 +- .../kmath/histogram/TreeHistogramTest.kt | 2 +- kmath-jafama/README.md | 6 +- kmath-jupyter/README.md | 6 +- .../kscience/kmath/jupyter/KMathJupyter.kt | 2 +- kmath-kotlingrad/README.md | 6 +- kmath-memory/README.md | 6 +- kmath-memory/build.gradle.kts | 1 + .../space/kscience/kmath}/annotations.kt | 4 +- .../space/kscience/kmath/memory/Memory.kt | 15 ++--- .../kscience/kmath/memory/DataViewMemory.kt | 4 +- .../kscience/kmath/memory/ByteBufferMemory.kt | 4 +- .../kscience/kmath/memory/NativeMemory.kt | 4 +- .../space/kscience/kmath/memory/WasmMemory.kt | 66 +++++++++++++++++++ kmath-multik/README.md | 6 +- .../kmath/multik/MultikDoubleAlgebra.kt | 2 +- .../kscience/kmath/multik/MultikTensor.kt | 2 +- .../kmath/multik/MultikTensorAlgebra.kt | 7 +- .../kscience/kmath/multik/MultikNDTest.kt | 2 +- kmath-nd4j/README.md | 6 +- .../kscience/kmath/nd4j/Nd4jArrayAlgebra.kt | 6 +- .../kscience/kmath/nd4j/Nd4jArrayStructure.kt | 2 +- .../kscience/kmath/nd4j/Nd4jTensorAlgebra.kt | 4 +- .../kmath/nd4j/Nd4jArrayAlgebraTest.kt | 2 +- .../kmath/nd4j/Nd4jArrayStructureTest.kt | 2 +- kmath-optimization/README.md | 6 +- .../kmath/optimization/QowOptimizer.kt | 2 +- .../kscience/kmath/optimization/XYFit.kt | 2 +- .../kmath/optimization/logLikelihood.kt | 2 +- kmath-stat/README.md | 6 +- kmath-stat/build.gradle.kts | 2 +- .../space/kscience/kmath/samplers/Sampler.kt | 2 +- .../kmath/series/MonotonicSeriesAlgebra.kt | 8 +-- .../kscience/kmath/series/SeriesAlgebra.kt | 39 +++++++---- .../space/kscience/kmath/series/resampling.kt | 22 +++++++ .../kscience/kmath/stat/StatisticalAlgebra.kt | 4 +- .../space/kscience/kmath/series/TestSeries.kt | 28 ++++++++ kmath-symja/README.md | 6 +- kmath-tensorflow/README.md | 6 +- .../tensorflow/DoubleTensorFlowAlgebra.kt | 4 +- .../kmath/tensorflow/TensorFlowAlgebra.kt | 6 +- .../kmath/tensorflow/DoubleTensorFlowOps.kt | 2 +- kmath-tensors/README.md | 6 +- .../core/BroadcastDoubleTensorAlgebra.kt | 2 +- .../kmath/tensors/core/BufferedTensor.kt | 2 +- .../kmath/tensors/core/DoubleTensor.kt | 7 +- .../kmath/tensors/core/DoubleTensor1D.kt | 2 +- .../kmath/tensors/core/DoubleTensor2D.kt | 2 +- .../kmath/tensors/core/DoubleTensorAlgebra.kt | 11 ++-- .../kscience/kmath/tensors/core/IntTensor.kt | 2 +- .../kmath/tensors/core/IntTensorAlgebra.kt | 2 +- .../tensors/core/internal/broadcastUtils.kt | 2 +- .../kmath/tensors/core/internal/utils.kt | 2 +- .../tensors/core/tensorAlgebraExtensions.kt | 2 +- .../kmath/tensors/core/TestDoubleTensor.kt | 3 +- kmath-viktor/README.md | 6 +- .../kscience/kmath/viktor/ViktorFieldOpsND.kt | 6 +- .../kmath/viktor/ViktorStructureND.kt | 2 +- test-utils/build.gradle.kts | 1 + 190 files changed, 485 insertions(+), 350 deletions(-) rename examples/src/main/kotlin/space/kscience/kmath/{stat => series}/DateTimeSeries.kt (79%) create mode 100644 kmath-core/src/wasmMain/kotlin/space/kscience/kmath/misc/numbers.kt create mode 100644 kmath-core/src/wasmMain/kotlin/space/kscience/kmath/operations/isInteger.kt rename {kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc => kmath-memory/src/commonMain/kotlin/space/kscience/kmath}/annotations.kt (95%) create mode 100644 kmath-memory/src/wasmMain/kotlin/space/kscience/kmath/memory/WasmMemory.kt create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/resampling.kt create mode 100644 kmath-stat/src/commonTest/kotlin/space/kscience/kmath/series/TestSeries.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 24b592430..0d4e6123b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,7 @@ ### Changed +- Annotations moved to `space.kscience.kmath` - Exponential operations merged with hyperbolic functions - Space is replaced by Group. Space is reserved for vector spaces. - VectorSpace is now a vector space diff --git a/README.md b/README.md index 03e803180..dbd670264 100644 --- a/README.md +++ b/README.md @@ -214,28 +214,6 @@ One can still use generic algebras though. > > **Maturity**: EXPERIMENTAL -### [kmath-polynomial](kmath-polynomial) -> -> -> **Maturity**: PROTOTYPE -> -> **Features:** -> - [polynomial abstraction](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt) : Abstraction for polynomial spaces. -> - [rational function abstraction](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt) : Abstraction for rational functions spaces. -> - ["list" polynomials](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt) : List implementation of univariate polynomials. -> - ["list" rational functions](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt) : List implementation of univariate rational functions. -> - ["list" polynomials and rational functions constructors](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt) : Constructors for list polynomials and rational functions. -> - ["list" polynomials and rational functions utilities](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/listUtil.kt) : Utilities for list polynomials and rational functions. -> - ["numbered" polynomials](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt) : Numbered implementation of multivariate polynomials. -> - ["numbered" rational functions](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt) : Numbered implementation of multivariate rational functions. -> - ["numbered" polynomials and rational functions constructors](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt) : Constructors for numbered polynomials and rational functions. -> - ["numbered" polynomials and rational functions utilities](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/numberedUtil.kt) : Utilities for numbered polynomials and rational functions. -> - ["labeled" polynomials](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt) : Labeled implementation of multivariate polynomials. -> - ["labeled" rational functions](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt) : Labeled implementation of multivariate rational functions. -> - ["labeled" polynomials and rational functions constructors](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt) : Constructors for labeled polynomials and rational functions. -> - ["labeled" polynomials and rational functions utilities](kmath-polynomial/src/commonMain/kotlin/space/kscience/kmath/functions/labeledUtil.kt) : Utilities for labeled polynomials and rational functions. - - ### [kmath-stat](kmath-stat) > > @@ -262,11 +240,6 @@ One can still use generic algebras though. > - [linear algebra operations](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Advanced linear algebra operations like LU decomposition, SVD, etc. -### [kmath-trajectory](kmath-trajectory) -> Path and trajectory optimization -> -> **Maturity**: PROTOTYPE - ### [kmath-viktor](kmath-viktor) > > @@ -325,4 +298,4 @@ Gradle `6.0+` is required for multiplatform artifacts. The project requires a lot of additional work. The most important thing we need is a feedback about what features are required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues marked with -[waiting for a hero](https://github.com/SciProgCentre/kmath/labels/waiting%20for%20a%20hero) label. \ No newline at end of file +[waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero) label. \ No newline at end of file diff --git a/benchmarks/src/jsMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt b/benchmarks/src/jsMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt index fd1b4307a..cb07e489a 100644 --- a/benchmarks/src/jsMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt +++ b/benchmarks/src/jsMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt @@ -9,8 +9,8 @@ import kotlinx.benchmark.Benchmark import kotlinx.benchmark.Blackhole import kotlinx.benchmark.Scope import kotlinx.benchmark.State +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.expressions.* -import space.kscience.kmath.operations.Algebra import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.invoke @@ -94,6 +94,7 @@ class ExpressionsInterpretersBenchmark { } private val mst = node.toExpression(DoubleField) + @OptIn(UnstableKMathAPI::class) private val wasm = node.wasmCompileToExpression(DoubleField) private val estree = node.estreeCompileToExpression(DoubleField) diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt index 19795b9eb..d07b7b4df 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt @@ -10,7 +10,7 @@ import kotlinx.benchmark.Blackhole import org.openjdk.jmh.annotations.Benchmark import org.openjdk.jmh.annotations.Scope import org.openjdk.jmh.annotations.State -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.operations.BigIntField import space.kscience.kmath.operations.JBigIntegerField import space.kscience.kmath.operations.invoke 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 3d39e89a5..fb8d845e8 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt @@ -13,7 +13,7 @@ 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.misc.UnsafeKMathAPI +import space.kscience.kmath.UnsafeKMathAPI import space.kscience.kmath.nd.* import space.kscience.kmath.nd4j.nd4j import space.kscience.kmath.operations.DoubleField diff --git a/build.gradle.kts b/build.gradle.kts index cd8dfb4a0..2eea9c47b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,7 +15,7 @@ allprojects { } group = "space.kscience" - version = "0.3.1-dev-11" + version = "0.4.0-dev-1" } subprojects { diff --git a/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt b/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt index 183510232..d973ebae4 100644 --- a/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt +++ b/buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt @@ -385,7 +385,7 @@ import org.ejml.sparse.csc.factory.LinearSolverFactory_DSCC import org.ejml.sparse.csc.factory.LinearSolverFactory_FSCC import space.kscience.kmath.linear.* import space.kscience.kmath.linear.Matrix -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.nd.StructureFeature import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.FloatField diff --git a/examples/src/main/kotlin/space/kscience/kmath/stat/DateTimeSeries.kt b/examples/src/main/kotlin/space/kscience/kmath/series/DateTimeSeries.kt similarity index 79% rename from examples/src/main/kotlin/space/kscience/kmath/stat/DateTimeSeries.kt rename to examples/src/main/kotlin/space/kscience/kmath/series/DateTimeSeries.kt index 9836db6ea..ca10fc290 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/stat/DateTimeSeries.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/series/DateTimeSeries.kt @@ -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. */ -package space.kscience.kmath.stat +package space.kscience.kmath.series 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( 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 c94cb0e71..0e10f1a9a 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/series/analyzeDif.kt @@ -1,9 +1,8 @@ package space.kscience.kmath.series -import kotlinx.html.FlowContent import kotlinx.html.h1 -import space.kscience.kmath.operations.DoubleBufferOps +import kotlinx.html.p import space.kscience.kmath.operations.algebra import space.kscience.kmath.operations.bufferAlgebra import space.kscience.kmath.operations.toList @@ -15,35 +14,43 @@ import space.kscience.plotly.* import kotlin.math.PI fun main() = with(Double.algebra.bufferAlgebra.seriesAlgebra()) { - fun FlowContent.plotSeries(buffer: Buffer) { - val ls = buffer.labels - plot { - scatter { - x.numbers = ls - y.numbers = buffer.toList() - } + + + fun Plot.plotSeries(name: String, buffer: Buffer) { + scatter { + this.name = name + x.numbers = buffer.labels + y.numbers = buffer.toList() + } + } + + + val s1 = series(100) { sin(2 * PI * it / 100) + 1.0 } + + val s2 = s1.slice(20..50).moveTo(40) + + val s3: Buffer = s1.zip(s2) { l, r -> l + r } //s1 + s2 + val s4 = s3.map { ln(it) } + + val kmTest: KMComparisonResult = ksComparisonStatistic(s1, s2) + + Plotly.page { + h1 { +"This is my plot" } + p{ + +"Kolmogorov-smirnov test for s1 and s2: ${kmTest.value}" + } + plot{ + plotSeries("s1", s1) + plotSeries("s2", s2) + plotSeries("s3", s3) + plotSeries("s4", s4) layout { xaxis { range(0.0..100.0) } } } - } - - val s1 = series(100) { sin(2 * PI * it / 100) + 1.0 } - 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) - - @Suppress("UNUSED_VARIABLE") val kmTest: KMComparisonResult = ksComparisonStatistic(s1, s2) - - Plotly.page { - h1 { +"This is my plot" } - plotSeries(s1) - plotSeries(s2) - plotSeries(s4) }.makeFile() } \ 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 67c9b421f..2ce2c21a6 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StreamDoubleFieldND.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.structures -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.nd.* import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.ExtendedField 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 e3e7daaae..e6ff0ee28 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/structures/StructureReadBenchmark.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.structures -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.nd.BufferND import space.kscience.kmath.nd.ColumnStrides import space.kscience.kmath.nd.ShapeND diff --git a/kmath-ast/README.md b/kmath-ast/README.md index c6da64982..d85a18e1c 100644 --- a/kmath-ast/README.md +++ b/kmath-ast/README.md @@ -10,7 +10,7 @@ Extensions to MST API: transformations, dynamic compilation and visualization. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.1-dev-1`. +The Maven coordinates of this project are `space.kscience:kmath-ast:0.4.0-dev-1`. **Gradle Groovy:** ```groovy @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ast:0.3.1-dev-1' + implementation 'space.kscience:kmath-ast:0.4.0-dev-1' } ``` **Gradle Kotlin DSL:** @@ -31,7 +31,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ast:0.3.1-dev-1") + implementation("space.kscience:kmath-ast:0.4.0-dev-1") } ``` diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/TypedMst.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/TypedMst.kt index 6458dc123..e211259af 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/TypedMst.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/TypedMst.kt @@ -5,9 +5,9 @@ package space.kscience.kmath.ast +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Algebra import space.kscience.kmath.operations.NumericAlgebra diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/evaluateConstants.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/evaluateConstants.kt index e411cd251..fb0c9b872 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/evaluateConstants.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/evaluateConstants.kt @@ -5,9 +5,9 @@ package space.kscience.kmath.ast +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Algebra import space.kscience.kmath.operations.NumericAlgebra import space.kscience.kmath.operations.bindSymbolOrNull diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt index 13806703c..50162a4f5 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.ast.rendering -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI /** * [SyntaxRenderer] implementation for LaTeX. diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt index bd941745b..bb49c5df4 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.ast.rendering -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI /** * [SyntaxRenderer] implementation for MathML. diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt index dd8ed3457..afa25febe 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt @@ -5,8 +5,8 @@ package space.kscience.kmath.ast.rendering +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.expressions.MST -import space.kscience.kmath.misc.UnstableKMathAPI /** * Renders [MST] to [MathSyntax]. diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt index 14df5ad8d..887469164 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.ast.rendering -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI /** * Syntax node for mathematical typography. diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt index e19a9722e..7669be664 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.ast.rendering -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI /** * Abstraction of writing [MathSyntax] as a string of an actual markup language. Typical implementation should diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt index c1a895015..8bb7e3585 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt @@ -5,10 +5,10 @@ package space.kscience.kmath.ast.rendering +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.ast.rendering.FeaturedMathRenderer.RenderFeature import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* import kotlin.reflect.KClass diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt index f42237ba6..2399e8f68 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt @@ -5,8 +5,8 @@ package space.kscience.kmath.ast.rendering +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.ast.rendering.FeaturedMathRendererWithPostProcess.PostProcessPhase -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.FieldOps import space.kscience.kmath.operations.GroupOps import space.kscience.kmath.operations.PowerOperations diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt index 853f5f983..87c2df2d2 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.estree +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.ast.TypedMst import space.kscience.kmath.ast.evaluateConstants import space.kscience.kmath.estree.internal.ESTreeBuilder @@ -13,7 +14,6 @@ import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.expressions.invoke import space.kscience.kmath.internal.estree.BaseExpression -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Algebra /** diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt index d29fbde55..1908f0659 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/internal/WasmBuilder.kt @@ -5,11 +5,11 @@ package space.kscience.kmath.wasm.internal +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.ast.TypedMst import space.kscience.kmath.expressions.* import space.kscience.kmath.internal.binaryen.* import space.kscience.kmath.internal.webassembly.Instance -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* import space.kscience.kmath.internal.binaryen.Module as BinaryenModule import space.kscience.kmath.internal.webassembly.Module as WasmModule diff --git a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt index 6a20da799..acb26f918 100644 --- a/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt +++ b/kmath-ast/src/jsMain/kotlin/space/kscience/kmath/wasm/wasm.kt @@ -7,10 +7,10 @@ package space.kscience.kmath.wasm +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.ast.TypedMst import space.kscience.kmath.ast.evaluateConstants import space.kscience.kmath.expressions.* -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.IntRing import space.kscience.kmath.wasm.internal.DoubleWasmBuilder diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt index 59a26af7d..7094d0442 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt @@ -7,11 +7,11 @@ package space.kscience.kmath.asm +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.asm.internal.* import space.kscience.kmath.ast.TypedMst import space.kscience.kmath.ast.evaluateConstants import space.kscience.kmath.expressions.* -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Algebra import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.IntRing diff --git a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/PrimitiveAsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/PrimitiveAsmBuilder.kt index d50318cd1..a3e5b7522 100644 --- a/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/PrimitiveAsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/internal/PrimitiveAsmBuilder.kt @@ -11,9 +11,9 @@ import org.objectweb.asm.Opcodes.* import org.objectweb.asm.Type import org.objectweb.asm.Type.* import org.objectweb.asm.commons.InstructionAdapter +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.ast.TypedMst import space.kscience.kmath.expressions.* -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* import java.lang.invoke.MethodHandles import java.lang.invoke.MethodType diff --git a/kmath-commons/README.md b/kmath-commons/README.md index 89f1f6c9f..47b61c409 100644 --- a/kmath-commons/README.md +++ b/kmath-commons/README.md @@ -6,7 +6,7 @@ Commons math binding for kmath ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-commons:0.3.1-dev-1`. +The Maven coordinates of this project are `space.kscience:kmath-commons:0.4.0-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-commons:0.3.1-dev-1' + implementation 'space.kscience:kmath-commons:0.4.0-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-commons:0.3.1-dev-1") + implementation("space.kscience:kmath-commons:0.4.0-dev-1") } ``` 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 cb7fb543f..38eaf8868 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 @@ -8,8 +8,8 @@ package space.kscience.kmath.commons.expressions import org.apache.commons.math3.analysis.differentiation.DerivativeStructure +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.expressions.* -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.NumbersAddOps diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt index 4839518e6..c3e581d31 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/integration/CMIntegrator.kt @@ -7,8 +7,8 @@ package space.kscience.kmath.commons.integration import org.apache.commons.math3.analysis.integration.IterativeLegendreGaussIntegrator import org.apache.commons.math3.analysis.integration.SimpsonIntegrator +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.integration.* -import space.kscience.kmath.misc.UnstableKMathAPI /** * Integration wrapper for Common-maths UnivariateIntegrator diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt index e95c9115d..d19bd1be0 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/linear/CMMatrix.kt @@ -6,8 +6,8 @@ package space.kscience.kmath.commons.linear import org.apache.commons.math3.linear.* +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.linear.* -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.StructureFeature import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.structures.Buffer diff --git a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizer.kt b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizer.kt index 46baa7d50..c4dafb6a6 100644 --- a/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizer.kt +++ b/kmath-commons/src/main/kotlin/space/kscience/kmath/commons/optimization/CMOptimizer.kt @@ -13,11 +13,11 @@ import org.apache.commons.math3.optim.nonlinear.scalar.ObjectiveFunctionGradient import org.apache.commons.math3.optim.nonlinear.scalar.gradient.NonLinearConjugateGradientOptimizer import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.NelderMeadSimplex import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.SimplexOptimizer +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.expressions.SymbolIndexer import space.kscience.kmath.expressions.derivative import space.kscience.kmath.expressions.withSymbols -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.log import space.kscience.kmath.optimization.* import kotlin.collections.set diff --git a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt index 308f504af..6541736ce 100644 --- a/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt +++ b/kmath-commons/src/test/kotlin/space/kscience/kmath/commons/integration/IntegrationTest.kt @@ -6,9 +6,9 @@ package space.kscience.kmath.commons.integration import org.junit.jupiter.api.Test +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.integration.integrate import space.kscience.kmath.integration.value -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField.sin import kotlin.math.PI import kotlin.math.abs 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 03b1426f5..d2e86bb40 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,13 +6,13 @@ package space.kscience.kmath.commons.optimization import kotlinx.coroutines.runBlocking +import space.kscience.kmath.UnstableKMathAPI 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.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.* diff --git a/kmath-complex/README.md b/kmath-complex/README.md index f00952065..4e800b7ac 100644 --- a/kmath-complex/README.md +++ b/kmath-complex/README.md @@ -8,7 +8,7 @@ Complex and hypercomplex number systems in KMath. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.1-dev-1`. +The Maven coordinates of this project are `space.kscience:kmath-complex:0.4.0-dev-1`. **Gradle Groovy:** ```groovy @@ -18,7 +18,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-complex:0.3.1-dev-1' + implementation 'space.kscience:kmath-complex:0.4.0-dev-1' } ``` **Gradle Kotlin DSL:** @@ -29,6 +29,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-complex:0.3.1-dev-1") + implementation("space.kscience:kmath-complex:0.4.0-dev-1") } ``` 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 bb580989b..b5f1aabe7 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 @@ -5,10 +5,10 @@ package space.kscience.kmath.complex +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.memory.MemoryReader import space.kscience.kmath.memory.MemorySpec import space.kscience.kmath.memory.MemoryWriter -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* import space.kscience.kmath.structures.* import kotlin.math.* 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 06f6cad85..90a6b3253 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,8 +5,8 @@ package space.kscience.kmath.complex -import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.PerformancePitfall +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.nd.* import space.kscience.kmath.operations.* import space.kscience.kmath.structures.Buffer diff --git a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt index e9b42118f..d4259c4dc 100644 --- a/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt +++ b/kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt @@ -5,10 +5,10 @@ package space.kscience.kmath.complex +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.memory.MemoryReader import space.kscience.kmath.memory.MemorySpec import space.kscience.kmath.memory.MemoryWriter -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.MemoryBuffer diff --git a/kmath-core/README.md b/kmath-core/README.md index e84ca38d7..b58105d2f 100644 --- a/kmath-core/README.md +++ b/kmath-core/README.md @@ -15,7 +15,7 @@ performance calculations to code generation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-core:0.3.1-dev-1`. +The Maven coordinates of this project are `space.kscience:kmath-core:0.4.0-dev-1`. **Gradle Groovy:** ```groovy @@ -25,7 +25,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-core:0.3.1-dev-1' + implementation 'space.kscience:kmath-core:0.4.0-dev-1' } ``` **Gradle Kotlin DSL:** @@ -36,6 +36,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-core:0.3.1-dev-1") + implementation("space.kscience:kmath-core:0.4.0-dev-1") } ``` diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index 0e4646bed..b6a955b12 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -6,6 +6,7 @@ kscience{ jvm() js() native() +// wasm() dependencies { api(projects.kmathMemory) diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt index d09228e96..49e2ee8d0 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/ColumnarData.kt @@ -5,9 +5,9 @@ package space.kscience.kmath.data +import space.kscience.kmath.PerformancePitfall +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.structures.Buffer diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt index a3c3a2eda..de7e6f79b 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYColumnarData.kt @@ -5,9 +5,9 @@ package space.kscience.kmath.data +import space.kscience.kmath.PerformancePitfall +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.structures.Buffer import kotlin.math.max diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYErrorColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYErrorColumnarData.kt index dd0e35bc8..797a25443 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYErrorColumnarData.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYErrorColumnarData.kt @@ -5,8 +5,8 @@ package space.kscience.kmath.data +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt index 3dc1bb99b..846bbad62 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/data/XYZColumnarData.kt @@ -5,8 +5,8 @@ package space.kscience.kmath.data +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain1D.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain1D.kt index 10755e633..d619883b4 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain1D.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/Domain1D.kt @@ -5,8 +5,8 @@ package space.kscience.kmath.domains +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.linear.Point -import space.kscience.kmath.misc.UnstableKMathAPI @UnstableKMathAPI public abstract class Domain1D>(public val range: ClosedRange) : Domain { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/DoubleDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/DoubleDomain.kt index b0803f3e1..e56173624 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/DoubleDomain.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/DoubleDomain.kt @@ -4,7 +4,7 @@ */ package space.kscience.kmath.domains -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI /** * n-dimensional volume 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 7d5843a97..1049a251a 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 @@ -4,8 +4,8 @@ */ package space.kscience.kmath.domains +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.linear.Point -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.indices diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt index e8b867fac..5351a295d 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains/UnconstrainedDomain.kt @@ -4,8 +4,8 @@ */ package space.kscience.kmath.domains +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.linear.Point -import space.kscience.kmath.misc.UnstableKMathAPI @UnstableKMathAPI public class UnconstrainedDomain(override val dimension: Int) : DoubleDomain { 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 9e91ff26b..8c7cb0cf1 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 @@ -5,7 +5,7 @@ package space.kscience.kmath.expressions -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.operations.* import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.MutableBuffer 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 cf59efe71..f350303bc 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 @@ -5,7 +5,7 @@ package space.kscience.kmath.expressions -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.operations.Algebra import kotlin.jvm.JvmName import kotlin.properties.ReadOnlyProperty diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt index a75940cca..c894cf00a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/MstAlgebra.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.expressions -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.operations.* /** 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 24bdfce7e..5d047d5b7 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 @@ -7,9 +7,9 @@ package space.kscience.kmath.expressions +import space.kscience.kmath.PerformancePitfall +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.linear.Matrix -import space.kscience.kmath.misc.PerformancePitfall -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 { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt index f00e6d3f3..2bb5043b7 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt @@ -5,8 +5,8 @@ package space.kscience.kmath.expressions +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.linear.Point -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.* import space.kscience.kmath.structures.asBuffer import kotlin.contracts.InvocationKind diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt index e5f92efc9..7112e921a 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SymbolIndexer.kt @@ -5,8 +5,8 @@ package space.kscience.kmath.expressions +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.linear.Point -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.DoubleBuffer 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 5976b67b1..4bba47a91 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 @@ -5,7 +5,7 @@ package space.kscience.kmath.linear -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.nd.* import space.kscience.kmath.operations.* import space.kscience.kmath.structures.Buffer 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 4e7ab55ef..940af4a86 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 @@ -5,7 +5,7 @@ package space.kscience.kmath.linear -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.nd.* import space.kscience.kmath.operations.DoubleBufferOps import space.kscience.kmath.operations.DoubleField diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt index 757752115..a82bafe57 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LinearSpace.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.linear -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.nd.MutableStructure2D import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.nd.StructureFeature diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt index 0ee7c8828..650e7be5c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/LupDecomposition.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.linear -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.operations.* import space.kscience.kmath.structures.BufferAccessor2D import space.kscience.kmath.structures.DoubleBuffer diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt index d0105e4cd..4d2f01e68 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixBuilder.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.linear -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.operations.Ring import space.kscience.kmath.structures.BufferAccessor2D import space.kscience.kmath.structures.MutableBuffer diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt index feea26b40..46454a584 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/linear/MatrixWrapper.kt @@ -5,8 +5,8 @@ package space.kscience.kmath.linear +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.misc.FeatureSet -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.StructureFeature import space.kscience.kmath.operations.Ring import kotlin.reflect.KClass 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 index 90cc5bbfa..afa76d2a9 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/collections.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/collections.kt @@ -19,4 +19,4 @@ public inline fun List.zipWithNextCircular(transform: (a: T, b: T) -> } } -public inline fun List.zipWithNextCircular(): List> = zipWithNextCircular { l, r -> l to r } \ No newline at end of file +public fun List.zipWithNextCircular(): List> = zipWithNextCircular { l, r -> l to r } \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/sorting.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/sorting.kt index daf5e1eff..31b8c0037 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/sorting.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/sorting.kt @@ -6,6 +6,7 @@ package space.kscience.kmath.misc +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.VirtualBuffer 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 d53f5488a..91e26cc1b 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 @@ -5,8 +5,8 @@ package space.kscience.kmath.nd -import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.PerformancePitfall +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.operations.* import kotlin.reflect.KClass 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 781d2e367..74c63e6e2 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 @@ -7,8 +7,8 @@ package space.kscience.kmath.nd -import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.PerformancePitfall +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.operations.* public interface BufferAlgebraND> : AlgebraND { 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 a6bab8be1..9217f6fdc 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,7 +5,7 @@ package space.kscience.kmath.nd -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.BufferFactory import space.kscience.kmath.structures.MutableBuffer 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 b5ed64108..265d1eec8 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 @@ -5,8 +5,8 @@ package space.kscience.kmath.nd -import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.PerformancePitfall +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.operations.* import space.kscience.kmath.structures.DoubleBuffer import kotlin.contracts.InvocationKind 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 f46defeee..1491950d6 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 @@ -5,7 +5,7 @@ package space.kscience.kmath.nd -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.operations.IntRing import space.kscience.kmath.operations.NumbersAddOps import space.kscience.kmath.operations.bufferAlgebra 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 e4ba72cec..6c35e2f44 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 @@ -5,7 +5,7 @@ package space.kscience.kmath.nd -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall public class PermutedStructureND( 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 index 63728e94f..d43ebaf1c 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/ShapeND.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.nd -import space.kscience.kmath.misc.UnsafeKMathAPI +import space.kscience.kmath.UnsafeKMathAPI import kotlin.jvm.JvmInline /** 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 34d748b3f..1b4647146 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 @@ -5,7 +5,7 @@ package space.kscience.kmath.nd -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.operations.NumbersAddOps import space.kscience.kmath.operations.ShortRing import space.kscience.kmath.operations.bufferAlgebra 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 ba48e25ce..984b5ad0f 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 @@ -5,7 +5,7 @@ package space.kscience.kmath.nd -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.operations.asSequence import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.MutableBuffer 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 a9c6c2748..e006d09eb 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 @@ -5,7 +5,7 @@ package space.kscience.kmath.nd -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.structures.MutableListBuffer 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 c96843651..e643186ba 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 @@ -5,10 +5,10 @@ package space.kscience.kmath.nd +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.linear.LinearSpace import space.kscience.kmath.misc.Feature import space.kscience.kmath.misc.Featured -import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.Buffer 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 4932dca41..606b9a631 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,8 +5,8 @@ package space.kscience.kmath.nd -import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.PerformancePitfall +import space.kscience.kmath.UnstableKMathAPI public open class VirtualStructureND( override val shape: ShapeND, 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 424081738..40db5187f 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,7 +5,7 @@ package space.kscience.kmath.nd -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall @OptIn(PerformancePitfall::class) public fun StructureND.roll(axis: Int, step: Int = 1): StructureND { 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 index f50233ecc..28e32363f 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/primitiveStructureND.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/nd/primitiveStructureND.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.nd -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall public interface StructureNDOfDouble : StructureND { /** diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt index a7a5bc5fd..0960ab023 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt @@ -5,8 +5,8 @@ package space.kscience.kmath.operations +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.expressions.Symbol -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Ring.Companion.optimizedPower import space.kscience.kmath.structures.MutableBufferFactory diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt index 8730ff163..34a6d4a80 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/BigInt.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.operations -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.nd.BufferedRingOpsND import space.kscience.kmath.operations.BigInt.Companion.BASE import space.kscience.kmath.operations.BigInt.Companion.BASE_SIZE 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 7ba1a7066..74b41be9d 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 @@ -5,10 +5,11 @@ package space.kscience.kmath.operations +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.linear.Point -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.* -import kotlin.math.* +import kotlin.math.pow +import kotlin.math.sqrt /** * [ExtendedFieldOps] over [DoubleBuffer]. diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/LogicAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/LogicAlgebra.kt index 5cf98c7d5..7aa5aed80 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/LogicAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/LogicAlgebra.kt @@ -5,9 +5,9 @@ package space.kscience.kmath.operations +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.expressions.symbol -import space.kscience.kmath.misc.UnstableKMathAPI /** * An algebra for generic boolean logic diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt index 5c2747686..9bcfb00a2 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/NumericAlgebra.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.operations -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import kotlin.math.E import kotlin.math.PI 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 84fb2ea41..ddf599240 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,7 +5,7 @@ package space.kscience.kmath.operations -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.structures.Buffer /** 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 697939bdf..02fd2600d 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 @@ -1,6 +1,6 @@ package space.kscience.kmath.structures -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI /** * A buffer that wraps an original buffer diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MemoryBuffer.kt b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MemoryBuffer.kt index 80d5033c4..cbfd6b9cd 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MemoryBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/MemoryBuffer.kt @@ -17,9 +17,7 @@ import space.kscience.kmath.memory.* public open class MemoryBuffer(protected val memory: Memory, protected val spec: MemorySpec) : Buffer { override val size: Int get() = memory.size / spec.objectSize - private val reader: MemoryReader = memory.reader() - - override operator fun get(index: Int): T = reader.read(spec, spec.objectSize * index) + override operator fun get(index: Int): T = memory.read { read(spec, spec.objectSize * index) } override operator fun iterator(): Iterator = (0 until size).asSequence().map { get(it) }.iterator() override fun toString(): String = Buffer.toString(this) 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 0a475187f..6a7b6d836 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 @@ -5,7 +5,7 @@ package space.kscience.kmath.operations -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.structures.* /** 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 2f2cc80b3..791d7d16f 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 @@ -1,6 +1,6 @@ package space.kscience.kmath.structures -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI /** * Non-boxing access to primitive [Double] 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 0bfcb04a7..871119f48 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 @@ -7,7 +7,7 @@ package space.kscience.kmath.expressions -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField import kotlin.contracts.InvocationKind import kotlin.contracts.contract diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt index 6f207eab3..83f00ce6c 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/expressions/InterpretTest.kt @@ -5,8 +5,8 @@ package space.kscience.kmath.expressions +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.expressions.Symbol.Companion.x -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.BooleanAlgebra import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.invoke diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt index 25e29f3d6..4d05f9043 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/DoubleLUSolverTest.kt @@ -5,8 +5,8 @@ package space.kscience.kmath.linear -import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.PerformancePitfall +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.algebra import kotlin.test.Test diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt index fe5ea3642..531aee259 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/linear/MatrixTest.kt @@ -5,8 +5,8 @@ package space.kscience.kmath.linear -import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.PerformancePitfall +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.as2D import space.kscience.kmath.operations.algebra diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt index f4f7b1a51..06a9ab439 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/operations/BigIntAlgebraTest.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.operations -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.testutils.RingVerifier import kotlin.math.pow import kotlin.test.Test 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 147488273..1572db816 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 @@ -5,13 +5,18 @@ package space.kscience.kmath.structures +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.linear.linearSpace -import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.nd.* +import space.kscience.kmath.nd.StructureND +import space.kscience.kmath.nd.get +import space.kscience.kmath.nd.ndAlgebra +import space.kscience.kmath.nd.structureND import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.Norm import space.kscience.kmath.operations.algebra import space.kscience.kmath.operations.invoke +import kotlin.collections.component1 +import kotlin.collections.component2 import kotlin.math.abs import kotlin.math.pow import kotlin.test.Test diff --git a/kmath-core/src/wasmMain/kotlin/space/kscience/kmath/misc/numbers.kt b/kmath-core/src/wasmMain/kotlin/space/kscience/kmath/misc/numbers.kt new file mode 100644 index 000000000..e320f350e --- /dev/null +++ b/kmath-core/src/wasmMain/kotlin/space/kscience/kmath/misc/numbers.kt @@ -0,0 +1,12 @@ +/* + * 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 + +public actual fun Long.toIntExact(): Int { + val i = toInt() + if (i.toLong() == this) throw ArithmeticException("integer overflow") + return i +} diff --git a/kmath-core/src/wasmMain/kotlin/space/kscience/kmath/operations/isInteger.kt b/kmath-core/src/wasmMain/kotlin/space/kscience/kmath/operations/isInteger.kt new file mode 100644 index 000000000..11c82bf9e --- /dev/null +++ b/kmath-core/src/wasmMain/kotlin/space/kscience/kmath/operations/isInteger.kt @@ -0,0 +1,12 @@ +/* + * 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.operations + +/** + * Check if number is an integer from platform point of view + */ +public actual fun Number.isInteger(): Boolean = + (this is Int) || (this is Long) || (this is Short) || (this.toDouble() % 1 == 0.0) \ No newline at end of file diff --git a/kmath-coroutines/README.md b/kmath-coroutines/README.md index 337d8e037..21831e514 100644 --- a/kmath-coroutines/README.md +++ b/kmath-coroutines/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-coroutines:0.3.1-dev-1`. +The Maven coordinates of this project are `space.kscience:kmath-coroutines:0.4.0-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-coroutines:0.3.1-dev-1' + implementation 'space.kscience:kmath-coroutines:0.4.0-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-coroutines:0.3.1-dev-1") + implementation("space.kscience:kmath-coroutines:0.4.0-dev-1") } ``` diff --git a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt index ed0283630..977346e68 100644 --- a/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt +++ b/kmath-coroutines/src/commonMain/kotlin/space/kscience/kmath/chains/Chain.kt @@ -10,7 +10,7 @@ import kotlinx.coroutines.flow.FlowCollector import kotlinx.coroutines.flow.flow import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI /** * A not-necessary-Markov chain of some type 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 1f717658e..22c2ac3ff 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 @@ -6,8 +6,8 @@ package space.kscience.kmath.structures import kotlinx.coroutines.* +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.coroutines.Math -import space.kscience.kmath.misc.PerformancePitfall import space.kscience.kmath.nd.ColumnStrides import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.StructureND diff --git a/kmath-dimensions/README.md b/kmath-dimensions/README.md index 12aa2a7fa..2e7250b51 100644 --- a/kmath-dimensions/README.md +++ b/kmath-dimensions/README.md @@ -6,7 +6,7 @@ A proof of concept module for adding type-safe dimensions to structures ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-dimensions:0.3.1-dev-1`. +The Maven coordinates of this project are `space.kscience:kmath-dimensions:0.4.0-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-dimensions:0.3.1-dev-1' + implementation 'space.kscience:kmath-dimensions:0.4.0-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-dimensions:0.3.1-dev-1") + implementation("space.kscience:kmath-dimensions:0.4.0-dev-1") } ``` diff --git a/kmath-ejml/README.md b/kmath-ejml/README.md index 2d6c661e4..ad80ba183 100644 --- a/kmath-ejml/README.md +++ b/kmath-ejml/README.md @@ -9,7 +9,7 @@ EJML based linear algebra implementation. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.1-dev-1`. +The Maven coordinates of this project are `space.kscience:kmath-ejml:0.4.0-dev-1`. **Gradle Groovy:** ```groovy @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-ejml:0.3.1-dev-1' + implementation 'space.kscience:kmath-ejml:0.4.0-dev-1' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-ejml:0.3.1-dev-1") + implementation("space.kscience:kmath-ejml:0.4.0-dev-1") } ``` diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt index beb79fc0e..8925fb045 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt @@ -5,11 +5,11 @@ package space.kscience.kmath.ejml +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.linear.InverseMatrixFeature import space.kscience.kmath.linear.LinearSpace import space.kscience.kmath.linear.Matrix import space.kscience.kmath.linear.Point -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.operations.Ring diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt index aac327a84..c56583fa8 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt @@ -19,9 +19,9 @@ import org.ejml.sparse.csc.factory.DecompositionFactory_DSCC import org.ejml.sparse.csc.factory.DecompositionFactory_FSCC import org.ejml.sparse.csc.factory.LinearSolverFactory_DSCC import org.ejml.sparse.csc.factory.LinearSolverFactory_FSCC +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.linear.* import space.kscience.kmath.linear.Matrix -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.StructureFeature import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.FloatField 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 d1ae80ef9..e89810e0d 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 @@ -11,9 +11,9 @@ import org.ejml.data.DMatrixRMaj import org.ejml.dense.row.CommonOps_DDRM import org.ejml.dense.row.RandomMatrices_DDRM import org.ejml.dense.row.factory.DecompositionFactory_DDRM +import space.kscience.kmath.PerformancePitfall +import space.kscience.kmath.UnstableKMathAPI 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 diff --git a/kmath-for-real/README.md b/kmath-for-real/README.md index 5a8376976..638b15bfa 100644 --- a/kmath-for-real/README.md +++ b/kmath-for-real/README.md @@ -9,7 +9,7 @@ Specialization of KMath APIs for Double numbers. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.1-dev-1`. +The Maven coordinates of this project are `space.kscience:kmath-for-real:0.4.0-dev-1`. **Gradle Groovy:** ```groovy @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-for-real:0.3.1-dev-1' + implementation 'space.kscience:kmath-for-real:0.4.0-dev-1' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-for-real:0.3.1-dev-1") + implementation("space.kscience:kmath-for-real:0.4.0-dev-1") } ``` diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/DoubleVector.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/DoubleVector.kt index e607786fb..411a35188 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/DoubleVector.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/DoubleVector.kt @@ -5,8 +5,8 @@ package space.kscience.kmath.real +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.linear.Point -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.DoubleL2Norm import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.MutableBuffer.Companion.double 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 cfa59bf32..40e4a91f1 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 @@ -8,9 +8,9 @@ package space.kscience.kmath.real +import space.kscience.kmath.PerformancePitfall +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.linear.* -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 diff --git a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt index 6403cf509..adb62b173 100644 --- a/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt +++ b/kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/grids.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.real -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.DoubleBuffer import kotlin.math.floor diff --git a/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/DoubleMatrixTest.kt b/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/DoubleMatrixTest.kt index 0d016116d..c00cd84d1 100644 --- a/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/DoubleMatrixTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/DoubleMatrixTest.kt @@ -5,10 +5,10 @@ package space.kscience.kmath.real +import space.kscience.kmath.PerformancePitfall +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.linear.linearSpace import space.kscience.kmath.linear.matrix -import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.algebra import space.kscience.kmath.testutils.contentEquals diff --git a/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/GridTest.kt b/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/GridTest.kt index 31be9a452..35c53f9d6 100644 --- a/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/GridTest.kt +++ b/kmath-for-real/src/commonTest/kotlin/space/kscience/kmath/real/GridTest.kt @@ -5,11 +5,7 @@ package space.kscience.kmath.real -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.real.DoubleVector -import space.kscience.kmath.real.minus -import space.kscience.kmath.real.norm -import space.kscience.kmath.real.step +import space.kscience.kmath.UnstableKMathAPI import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue diff --git a/kmath-functions/README.md b/kmath-functions/README.md index 1292424b5..929fd9172 100644 --- a/kmath-functions/README.md +++ b/kmath-functions/README.md @@ -11,7 +11,7 @@ Functions and interpolations. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.1-dev-1`. +The Maven coordinates of this project are `space.kscience:kmath-functions:0.4.0-dev-1`. **Gradle Groovy:** ```groovy @@ -21,7 +21,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-functions:0.3.1-dev-1' + implementation 'space.kscience:kmath-functions:0.4.0-dev-1' } ``` **Gradle Kotlin DSL:** @@ -32,6 +32,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-functions:0.3.1-dev-1") + implementation("space.kscience:kmath-functions:0.4.0-dev-1") } ``` diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt index a9f51f7b0..a9e75e456 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.functions -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.operations.Ring /** diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt index 5effe566a..0d4b93f03 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/polynomialUtil.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.functions -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.operations.* import kotlin.contracts.InvocationKind import kotlin.contracts.contract 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 603f0503a..f2ac0a296 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 @@ -4,7 +4,7 @@ */ package space.kscience.kmath.integration -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.operations.Field import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asBuffer diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt index 7e4ff0f8b..73a3cc25b 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SimpsonIntegrator.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.integration -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.invoke 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 c66674fbb..993812b29 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 @@ -5,13 +5,13 @@ package space.kscience.kmath.integration +import space.kscience.kmath.PerformancePitfall +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.functions.PiecewisePolynomial import space.kscience.kmath.functions.integrate import space.kscience.kmath.interpolation.PolynomialInterpolator 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.structures.Buffer import space.kscience.kmath.structures.DoubleBuffer diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt index af8c858fa..f18e86b80 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/UnivariateIntegrand.kt @@ -5,8 +5,8 @@ package space.kscience.kmath.integration +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.misc.FeatureSet -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.DoubleBuffer diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt index 52e8991b1..191e7dfd9 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt @@ -7,11 +7,11 @@ package space.kscience.kmath.interpolation +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.data.XYColumnarData import space.kscience.kmath.functions.PiecewisePolynomial import space.kscience.kmath.functions.asFunction import space.kscience.kmath.functions.value -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Ring import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.asBuffer diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt index 49d7fd1ca..5c56e406a 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt @@ -5,10 +5,10 @@ package space.kscience.kmath.interpolation +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.data.XYColumnarData import space.kscience.kmath.functions.PiecewisePolynomial import space.kscience.kmath.functions.Polynomial -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.invoke diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt index a63142be4..a3cc17954 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt @@ -5,10 +5,10 @@ package space.kscience.kmath.interpolation +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.data.XYColumnarData import space.kscience.kmath.functions.PiecewisePolynomial import space.kscience.kmath.functions.Polynomial -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.invoke diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt index c1b1008ae..48e641335 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/PolynomialUtilTest.kt @@ -5,9 +5,9 @@ package space.kscience.kmath.functions +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.functions.testUtils.Rational import space.kscience.kmath.functions.testUtils.RationalField -import space.kscience.kmath.misc.UnstableKMathAPI import kotlin.test.Test import kotlin.test.assertEquals diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt index 0a3d00e96..ff05805da 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/testUtils/Rational.kt @@ -7,7 +7,7 @@ package space.kscience.kmath.functions.testUtils -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.operations.Field import space.kscience.kmath.operations.NumbersAddOps diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt index 32fc08ae4..7424f3566 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/GaussIntegralTest.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.integration -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField import kotlin.math.PI import kotlin.math.sin diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SimpsonIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SimpsonIntegralTest.kt index 188f8d15f..7b699ebbc 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SimpsonIntegralTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SimpsonIntegralTest.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.integration -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField import kotlin.math.PI import kotlin.math.sin diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt index 4a15e96c3..b17d21abf 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/integration/SplineIntegralTest.kt @@ -5,9 +5,9 @@ package space.kscience.kmath.integration +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.functions.Polynomial import space.kscience.kmath.functions.integrate -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField import kotlin.math.PI import kotlin.math.sin diff --git a/kmath-geometry/README.md b/kmath-geometry/README.md index 72d275697..480945c4f 100644 --- a/kmath-geometry/README.md +++ b/kmath-geometry/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-geometry:0.3.1-dev-1`. +The Maven coordinates of this project are `space.kscience:kmath-geometry:0.4.0-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-geometry:0.3.1-dev-1' + implementation 'space.kscience:kmath-geometry:0.4.0-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-geometry:0.3.1-dev-1") + implementation("space.kscience:kmath-geometry:0.4.0-dev-1") } ``` diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/rotations3D.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/rotations3D.kt index 487af7e50..1f3850c7c 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/rotations3D.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/rotations3D.kt @@ -5,12 +5,15 @@ package space.kscience.kmath.geometry +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.complex.Quaternion import space.kscience.kmath.complex.QuaternionField import space.kscience.kmath.complex.normalized import space.kscience.kmath.complex.reciprocal -import space.kscience.kmath.linear.* -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.linear.LinearSpace +import space.kscience.kmath.linear.Matrix +import space.kscience.kmath.linear.linearSpace +import space.kscience.kmath.linear.matrix import space.kscience.kmath.operations.DoubleField import kotlin.math.pow import kotlin.math.sqrt diff --git a/kmath-histograms/README.md b/kmath-histograms/README.md index 5fd91ee0c..bc7f0fa5b 100644 --- a/kmath-histograms/README.md +++ b/kmath-histograms/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-histograms:0.3.1-dev-1`. +The Maven coordinates of this project are `space.kscience:kmath-histograms:0.4.0-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-histograms:0.3.1-dev-1' + implementation 'space.kscience:kmath-histograms:0.4.0-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-histograms:0.3.1-dev-1") + implementation("space.kscience:kmath-histograms:0.4.0-dev-1") } ``` diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram1D.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram1D.kt index f9ca6a486..f50610a17 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram1D.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/Histogram1D.kt @@ -5,10 +5,10 @@ package space.kscience.kmath.histogram +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.domains.Domain1D import space.kscience.kmath.domains.center import space.kscience.kmath.linear.Point -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.asSequence import space.kscience.kmath.structures.Buffer 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 623452422..5fdc2ffb0 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 @@ -5,9 +5,9 @@ package space.kscience.kmath.histogram +import space.kscience.kmath.PerformancePitfall 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.ShapeND diff --git a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogram1D.kt b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogram1D.kt index 3c687d2df..154d35350 100644 --- a/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogram1D.kt +++ b/kmath-histograms/src/commonMain/kotlin/space/kscience/kmath/histogram/UniformHistogram1D.kt @@ -5,8 +5,8 @@ package space.kscience.kmath.histogram +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.domains.DoubleDomain1D -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.ScaleOperations 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 b62780ed5..61ce450a7 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 @@ -7,10 +7,10 @@ package space.kscience.kmath.histogram +import space.kscience.kmath.PerformancePitfall +import space.kscience.kmath.UnstableKMathAPI 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.* import space.kscience.kmath.structures.* 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 64cc4f203..54806c9fa 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,8 +7,8 @@ package space.kscience.kmath.histogram -import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.PerformancePitfall +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.nd.ColumnStrides import space.kscience.kmath.operations.invoke import space.kscience.kmath.real.DoubleVector 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 c4554b575..fa129fad6 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 @@ -7,8 +7,8 @@ package space.kscience.kmath.histogram import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.distributions.NormalDistribution -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.stat.nextBuffer diff --git a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramGroup.kt b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramGroup.kt index a7d34ff71..772db7df3 100644 --- a/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramGroup.kt +++ b/kmath-histograms/src/jvmMain/kotlin/space/kscience/kmath/histogram/TreeHistogramGroup.kt @@ -7,9 +7,9 @@ package space.kscience.kmath.histogram +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.domains.DoubleDomain1D import space.kscience.kmath.domains.center -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.sorted import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.Ring diff --git a/kmath-histograms/src/jvmTest/kotlin/space/kscience/kmath/histogram/TreeHistogramTest.kt b/kmath-histograms/src/jvmTest/kotlin/space/kscience/kmath/histogram/TreeHistogramTest.kt index 77dc189ee..b7c1f34ba 100644 --- a/kmath-histograms/src/jvmTest/kotlin/space/kscience/kmath/histogram/TreeHistogramTest.kt +++ b/kmath-histograms/src/jvmTest/kotlin/space/kscience/kmath/histogram/TreeHistogramTest.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.histogram import org.junit.jupiter.api.Test -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.real.step import kotlin.random.Random diff --git a/kmath-jafama/README.md b/kmath-jafama/README.md index c008c76ca..47142f174 100644 --- a/kmath-jafama/README.md +++ b/kmath-jafama/README.md @@ -7,7 +7,7 @@ Integration with [Jafama](https://github.com/jeffhain/jafama). ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-jafama:0.3.1-dev-1`. +The Maven coordinates of this project are `space.kscience:kmath-jafama:0.4.0-dev-1`. **Gradle Groovy:** ```groovy @@ -17,7 +17,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-jafama:0.3.1-dev-1' + implementation 'space.kscience:kmath-jafama:0.4.0-dev-1' } ``` **Gradle Kotlin DSL:** @@ -28,7 +28,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-jafama:0.3.1-dev-1") + implementation("space.kscience:kmath-jafama:0.4.0-dev-1") } ``` diff --git a/kmath-jupyter/README.md b/kmath-jupyter/README.md index 3c9832625..2b26878dc 100644 --- a/kmath-jupyter/README.md +++ b/kmath-jupyter/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-jupyter:0.3.1-dev-1`. +The Maven coordinates of this project are `space.kscience:kmath-jupyter:0.4.0-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-jupyter:0.3.1-dev-1' + implementation 'space.kscience:kmath-jupyter:0.4.0-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-jupyter:0.3.1-dev-1") + implementation("space.kscience:kmath-jupyter:0.4.0-dev-1") } ``` 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 1fe9fe92f..2d32dd609 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 @@ -12,6 +12,7 @@ import kotlinx.html.unsafe import org.jetbrains.kotlinx.jupyter.api.DisplayResult import org.jetbrains.kotlinx.jupyter.api.HTML import org.jetbrains.kotlinx.jupyter.api.libraries.JupyterIntegration +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.ast.rendering.FeaturedMathRendererWithPostProcess import space.kscience.kmath.ast.rendering.MathMLSyntaxRenderer import space.kscience.kmath.ast.rendering.renderWithStringBuilder @@ -19,7 +20,6 @@ import space.kscience.kmath.complex.Complex import space.kscience.kmath.complex.Quaternion 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 diff --git a/kmath-kotlingrad/README.md b/kmath-kotlingrad/README.md index 457652aaf..f1a918b4b 100644 --- a/kmath-kotlingrad/README.md +++ b/kmath-kotlingrad/README.md @@ -8,7 +8,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-kotlingrad:0.3.1-dev-1`. +The Maven coordinates of this project are `space.kscience:kmath-kotlingrad:0.4.0-dev-1`. **Gradle Groovy:** ```groovy @@ -18,7 +18,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-kotlingrad:0.3.1-dev-1' + implementation 'space.kscience:kmath-kotlingrad:0.4.0-dev-1' } ``` **Gradle Kotlin DSL:** @@ -29,6 +29,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-kotlingrad:0.3.1-dev-1") + implementation("space.kscience:kmath-kotlingrad:0.4.0-dev-1") } ``` diff --git a/kmath-memory/README.md b/kmath-memory/README.md index 536d7f145..594588ecf 100644 --- a/kmath-memory/README.md +++ b/kmath-memory/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-memory:0.3.1-dev-1`. +The Maven coordinates of this project are `space.kscience:kmath-memory:0.4.0-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-memory:0.3.1-dev-1' + implementation 'space.kscience:kmath-memory:0.4.0-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-memory:0.3.1-dev-1") + implementation("space.kscience:kmath-memory:0.4.0-dev-1") } ``` diff --git a/kmath-memory/build.gradle.kts b/kmath-memory/build.gradle.kts index 4f0f996b9..d8af1e3a2 100644 --- a/kmath-memory/build.gradle.kts +++ b/kmath-memory/build.gradle.kts @@ -6,6 +6,7 @@ kscience { jvm() js() native() +// wasm() } readme { diff --git a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt b/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/annotations.kt similarity index 95% rename from kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt rename to kmath-memory/src/commonMain/kotlin/space/kscience/kmath/annotations.kt index 7da333a45..a95b166cf 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/annotations.kt +++ b/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/annotations.kt @@ -1,9 +1,9 @@ /* - * 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.misc +package space.kscience.kmath /** * Marks declarations that are still experimental in the KMath APIs, which means that the design of the corresponding diff --git a/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/Memory.kt b/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/Memory.kt index 006d57c5f..a63753015 100644 --- a/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/Memory.kt +++ b/kmath-memory/src/commonMain/kotlin/space/kscience/kmath/memory/Memory.kt @@ -43,7 +43,7 @@ public interface Memory { /** * The interface to read primitive types in this memory. */ -public interface MemoryReader { +public interface MemoryReader: AutoCloseable { /** * The underlying memory. */ @@ -82,7 +82,7 @@ public interface MemoryReader { /** * Disposes this reader if needed. */ - public fun release() + override fun close() } /** @@ -90,16 +90,13 @@ public interface MemoryReader { */ public inline fun Memory.read(block: MemoryReader.() -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - val reader = reader() - val result = reader.block() - reader.release() - return result + return reader().use(block) } /** * The interface to write primitive types into this memory. */ -public interface MemoryWriter { +public interface MemoryWriter: AutoCloseable { /** * The underlying memory. */ @@ -138,7 +135,7 @@ public interface MemoryWriter { /** * Disposes this writer if needed. */ - public fun release() + override fun close() } /** @@ -146,7 +143,7 @@ public interface MemoryWriter { */ public inline fun Memory.write(block: MemoryWriter.() -> Unit) { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - writer().apply(block).release() + writer().use(block) } /** diff --git a/kmath-memory/src/jsMain/kotlin/space/kscience/kmath/memory/DataViewMemory.kt b/kmath-memory/src/jsMain/kotlin/space/kscience/kmath/memory/DataViewMemory.kt index 40ba84c10..f8bcef010 100644 --- a/kmath-memory/src/jsMain/kotlin/space/kscience/kmath/memory/DataViewMemory.kt +++ b/kmath-memory/src/jsMain/kotlin/space/kscience/kmath/memory/DataViewMemory.kt @@ -41,7 +41,7 @@ private class DataViewMemory(val view: DataView) : Memory { override fun readLong(offset: Int): Long = view.getInt32(offset, false).toLong() shl 32 or view.getInt32(offset + 4, false).toLong() - override fun release() { + override fun close() { // does nothing on JS } } @@ -76,7 +76,7 @@ private class DataViewMemory(val view: DataView) : Memory { view.setInt32(offset + 4, (value and 0xffffffffL).toInt(), littleEndian = false) } - override fun release() { + override fun close() { // does nothing on JS } } diff --git a/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt b/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt index 84f7ea412..19910a396 100644 --- a/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt +++ b/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt @@ -53,7 +53,7 @@ internal class ByteBufferMemory( override fun readLong(offset: Int) = buffer.getLong(position(offset)) - override fun release() { + override fun close() { // does nothing on JVM } } @@ -87,7 +87,7 @@ internal class ByteBufferMemory( buffer.putLong(position(offset), value) } - override fun release() { + override fun close() { // does nothing on JVM } } diff --git a/kmath-memory/src/nativeMain/kotlin/space/kscience/kmath/memory/NativeMemory.kt b/kmath-memory/src/nativeMain/kotlin/space/kscience/kmath/memory/NativeMemory.kt index b224383e4..32bc8d6a5 100644 --- a/kmath-memory/src/nativeMain/kotlin/space/kscience/kmath/memory/NativeMemory.kt +++ b/kmath-memory/src/nativeMain/kotlin/space/kscience/kmath/memory/NativeMemory.kt @@ -41,7 +41,7 @@ internal class NativeMemory( override fun readLong(offset: Int) = array.getLongAt(position(offset)) - override fun release() { + override fun close() { // does nothing on JVM } } @@ -75,7 +75,7 @@ internal class NativeMemory( array.setLongAt(position(offset), value) } - override fun release() { + override fun close() { // does nothing on JVM } } diff --git a/kmath-memory/src/wasmMain/kotlin/space/kscience/kmath/memory/WasmMemory.kt b/kmath-memory/src/wasmMain/kotlin/space/kscience/kmath/memory/WasmMemory.kt new file mode 100644 index 000000000..7c2be19cc --- /dev/null +++ b/kmath-memory/src/wasmMain/kotlin/space/kscience/kmath/memory/WasmMemory.kt @@ -0,0 +1,66 @@ +/* + * 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.memory + +import kotlin.wasm.unsafe.Pointer +import kotlin.wasm.unsafe.UnsafeWasmMemoryApi + +@OptIn(UnsafeWasmMemoryApi::class) +public class WasmMemory private constructor( + public val pointer: Pointer, + override val size: Int, +) : Memory { + + override fun view(offset: Int, length: Int): Memory { + TODO("Not yet implemented") + } + + override fun copy(): Memory { + TODO("Not yet implemented") + } + + override fun reader(): MemoryReader = object : MemoryReader { + override val memory: Memory + get() = this@WasmMemory + + override fun readDouble(offset: Int): Double { + return Double.fromBits(pointer.plus(offset).loadLong()) + } + + override fun readFloat(offset: Int): Float { + return Float.fromBits(pointer.plus(offset).loadInt()) + } + + override fun readByte(offset: Int): Byte { + return pointer.plus(offset).loadByte() + } + + override fun readShort(offset: Int): Short { + return pointer.plus(offset).loadShort() + } + + override fun readInt(offset: Int): Int { + return pointer.plus(offset).loadInt() + } + + override fun readLong(offset: Int): Long { + return pointer.plus(offset).loadLong() + } + + override fun close() { + TODO() + } + + } + + override fun writer(): MemoryWriter = TODO() +} + +public actual fun Memory.Companion.allocate(length: Int): Memory { + TODO() +} + +public actual fun Memory.Companion.wrap(array: ByteArray): Memory = TODO() \ No newline at end of file diff --git a/kmath-multik/README.md b/kmath-multik/README.md index 0f5b65b4c..127b12a49 100644 --- a/kmath-multik/README.md +++ b/kmath-multik/README.md @@ -6,7 +6,7 @@ JetBrains Multik connector ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-multik:0.3.1-dev-1`. +The Maven coordinates of this project are `space.kscience:kmath-multik:0.4.0-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-multik:0.3.1-dev-1' + implementation 'space.kscience:kmath-multik:0.4.0-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-multik:0.3.1-dev-1") + implementation("space.kscience:kmath-multik:0.4.0-dev-1") } ``` diff --git a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt index 989ebcd5d..beab5c18b 100644 --- a/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt +++ b/kmath-multik/src/commonMain/kotlin/space/kscience/kmath/multik/MultikDoubleAlgebra.kt @@ -9,7 +9,7 @@ import org.jetbrains.kotlinx.multik.api.Engine import org.jetbrains.kotlinx.multik.api.Multik import org.jetbrains.kotlinx.multik.api.ndarrayOf import org.jetbrains.kotlinx.multik.ndarray.data.DataType -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.nd.StructureND import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.ExponentialOperations 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 ae526873d..59a9a1bf3 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 @@ -6,7 +6,7 @@ package space.kscience.kmath.multik import org.jetbrains.kotlinx.multik.ndarray.data.* -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.tensors.api.Tensor import kotlin.jvm.JvmInline 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 1736b48e3..c3a82b167 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 @@ -13,10 +13,11 @@ import org.jetbrains.kotlinx.multik.api.math.Math import org.jetbrains.kotlinx.multik.api.stat.Statistics import org.jetbrains.kotlinx.multik.ndarray.data.* import org.jetbrains.kotlinx.multik.ndarray.operations.* -import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.misc.UnsafeKMathAPI +import space.kscience.kmath.PerformancePitfall +import space.kscience.kmath.UnsafeKMathAPI import space.kscience.kmath.nd.* -import space.kscience.kmath.operations.* +import space.kscience.kmath.operations.Field +import space.kscience.kmath.operations.Ring import space.kscience.kmath.tensors.api.Tensor import space.kscience.kmath.tensors.api.TensorAlgebra import space.kscience.kmath.tensors.api.TensorPartialDivisionAlgebra 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 d52420fc6..1a130aa92 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 @@ -6,7 +6,7 @@ package space.kscience.kmath.multik import org.jetbrains.kotlinx.multik.default.DefaultEngine -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.one diff --git a/kmath-nd4j/README.md b/kmath-nd4j/README.md index bb065a300..b299c1b37 100644 --- a/kmath-nd4j/README.md +++ b/kmath-nd4j/README.md @@ -9,7 +9,7 @@ ND4J based implementations of KMath abstractions. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.1-dev-1`. +The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.4.0-dev-1`. **Gradle Groovy:** ```groovy @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-nd4j:0.3.1-dev-1' + implementation 'space.kscience:kmath-nd4j:0.4.0-dev-1' } ``` **Gradle Kotlin DSL:** @@ -30,7 +30,7 @@ repositories { } dependencies { - implementation("space.kscience:kmath-nd4j:0.3.1-dev-1") + implementation("space.kscience:kmath-nd4j:0.4.0-dev-1") } ``` 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 6f01233d7..0eb147b6f 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 @@ -10,9 +10,9 @@ import org.nd4j.linalg.api.ops.impl.transforms.strict.ACosh 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.PerformancePitfall +import space.kscience.kmath.UnsafeKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.nd.* import space.kscience.kmath.operations.* 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 a1405ccfb..93fbc8f85 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 @@ -6,7 +6,7 @@ package space.kscience.kmath.nd4j import org.nd4j.linalg.api.ndarray.INDArray -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.nd.* /** 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 ef7b7f257..5905739f8 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 @@ -12,8 +12,8 @@ import org.nd4j.linalg.api.ops.impl.transforms.strict.ASinh 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.misc.UnsafeKMathAPI +import space.kscience.kmath.PerformancePitfall +import space.kscience.kmath.UnsafeKMathAPI import space.kscience.kmath.nd.* import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.Field diff --git a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt index 9f1022fd9..708778e77 100644 --- a/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt +++ b/kmath-nd4j/src/test/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebraTest.kt @@ -6,7 +6,7 @@ package space.kscience.kmath.nd4j import org.nd4j.linalg.factory.Nd4j -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.one import space.kscience.kmath.nd.structureND 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 25c3fe23f..d57eb2e2d 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 @@ -6,7 +6,7 @@ package space.kscience.kmath.nd4j import org.nd4j.linalg.factory.Nd4j -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.nd.asList import space.kscience.kmath.nd.get import kotlin.test.Test diff --git a/kmath-optimization/README.md b/kmath-optimization/README.md index d7441ebd1..79a4f5d24 100644 --- a/kmath-optimization/README.md +++ b/kmath-optimization/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-optimization:0.3.1-dev-1`. +The Maven coordinates of this project are `space.kscience:kmath-optimization:0.4.0-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-optimization:0.3.1-dev-1' + implementation 'space.kscience:kmath-optimization:0.4.0-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-optimization:0.3.1-dev-1") + implementation("space.kscience:kmath-optimization:0.4.0-dev-1") } ``` 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 bbebec6af..b698584aa 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,9 +5,9 @@ package space.kscience.kmath.optimization +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.expressions.* import space.kscience.kmath.linear.* -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.log import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.DoubleL2Norm 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 5c28826ee..9e5396491 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 @@ -6,12 +6,12 @@ package space.kscience.kmath.optimization +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.data.XYColumnarData import space.kscience.kmath.data.indices import space.kscience.kmath.expressions.* import space.kscience.kmath.misc.FeatureSet import space.kscience.kmath.misc.Loggable -import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.ExtendedField import space.kscience.kmath.operations.bindSymbol import kotlin.math.pow diff --git a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/logLikelihood.kt b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/logLikelihood.kt index e0eeb339c..8ab9de48d 100644 --- a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/logLikelihood.kt +++ b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/logLikelihood.kt @@ -5,13 +5,13 @@ package space.kscience.kmath.optimization +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.data.XYColumnarData import space.kscience.kmath.data.indices import space.kscience.kmath.expressions.DifferentiableExpression import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.expressions.derivative -import space.kscience.kmath.misc.UnstableKMathAPI import kotlin.math.PI import kotlin.math.ln import kotlin.math.pow diff --git a/kmath-stat/README.md b/kmath-stat/README.md index 7ed20fcf4..e7e0a4d92 100644 --- a/kmath-stat/README.md +++ b/kmath-stat/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-stat:0.3.1-dev-1`. +The Maven coordinates of this project are `space.kscience:kmath-stat:0.4.0-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-stat:0.3.1-dev-1' + implementation 'space.kscience:kmath-stat:0.4.0-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-stat:0.3.1-dev-1") + implementation("space.kscience:kmath-stat:0.4.0-dev-1") } ``` diff --git a/kmath-stat/build.gradle.kts b/kmath-stat/build.gradle.kts index 267bfd0f3..1426e913a 100644 --- a/kmath-stat/build.gradle.kts +++ b/kmath-stat/build.gradle.kts @@ -12,7 +12,7 @@ kotlin.sourceSets { commonMain { dependencies { api(project(":kmath-coroutines")) - implementation(spclibs.atomicfu) + //implementation(spclibs.atomicfu) } } 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 52e400bf1..b87a429df 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 @@ -6,9 +6,9 @@ package space.kscience.kmath.stat import kotlinx.coroutines.flow.first +import space.kscience.kmath.UnstableKMathAPI 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 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 index 2bc363934..ed6f4e07b 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/MonotonicSeriesAlgebra.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/MonotonicSeriesAlgebra.kt @@ -37,11 +37,5 @@ public class MonotonicSeriesAlgebra, out BA : BufferAlgebra.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") + override fun Buffer.getByLabelOrNull(label: L): T? = getByOffsetOrNull(floorOffset(label)) } \ 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 1847e33b6..3ccbca5a1 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 @@ -112,14 +112,21 @@ public open class SeriesAlgebra, out BA : BufferAlgebra public val Buffer.startLabel: L get() = offsetToLabel(startOffset) /** - * Build a new series positioned at [startOffset]. + * Build a new series by offset 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(offsetToLabel(index)) - }.moveTo(startOffset) - } + public inline fun seriesByOffset( + size: Int, + startOffset: Int = 0, + crossinline block: A.(offset: Int) -> T, + ): Series = elementAlgebra.bufferFactory(size) { + elementAlgebra.block(it + startOffset) + }.moveTo(startOffset) + + /** + * Build a new series by label positioned at [startOffset]. + */ + public inline fun series(size: Int, startOffset: Int = 0, crossinline block: A.(label: L) -> T): Series = + seriesByOffset(size, startOffset) { offset -> block(offsetToLabel(offset)) } /** * Get a label buffer for given buffer. @@ -129,18 +136,24 @@ public open class SeriesAlgebra, out BA : BufferAlgebra /** * 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? { + public open fun Buffer.getByLabelOrNull(label: L): T? { val index = labels.indexOf(label) if (index == -1) return null return getByOffset(index + startOffset) } + /** + * Get value by label (rounded down) or throw [IndexOutOfBoundsException] if the value is outside series boundaries. + */ + public open fun Buffer.getByLabel(label: L): T = getByLabelOrNull(label) + ?: throw IndexOutOfBoundsException("Label $label is not in ${labels.first()}..${labels.last()}") + /** * Map a series to another series of the same size */ public inline fun Buffer.map(crossinline transform: A.(T) -> T): Series { val buf = elementAlgebra.bufferFactory(size) { - elementAlgebra.transform(getByOffset(it)) + elementAlgebra.transform(get(it)) } return buf.moveTo(offsetIndices.first) } @@ -178,12 +191,12 @@ public open class SeriesAlgebra, out BA : BufferAlgebra crossinline operation: A.(left: T, right: T) -> T, ): Series { val newRange = offsetIndices.intersect(other.offsetIndices) - return elementAlgebra.bufferFactory(newRange.size) { + return seriesByOffset(startOffset = newRange.first, size = newRange.last - newRange.first) { offset -> elementAlgebra.operation( - getByOffset(it), - other.getByOffset(it) + getByOffset(offset), + other.getByOffset(offset) ) - }.moveTo(newRange.first) + } } override fun Buffer.unaryMinus(): Buffer = map { -it } diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/resampling.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/resampling.kt new file mode 100644 index 000000000..dc21fe6d9 --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/resampling.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.series + +import space.kscience.kmath.operations.BufferAlgebra +import space.kscience.kmath.operations.Ring +import space.kscience.kmath.operations.sumWithGroupOf + +public fun , BA : BufferAlgebra, L : Comparable> MonotonicSeriesAlgebra.import( + data: List>, +): Series { + val groupedData: Map>> = data.groupBy { floorOffset(it.first) } + val minIndex = groupedData.minOf { it.key } + val maxIndex = groupedData.maxOf { it.key } + return elementAlgebra.bufferFactory(maxIndex - minIndex) { relativeIndex -> + val index = relativeIndex + minIndex + groupedData[index]?.sumWithGroupOf(elementAlgebra) { it.second } ?: elementAlgebra.zero + }.moveTo(minIndex) +} \ 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 index f36826c28..cce61519b 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,6 +1,6 @@ package space.kscience.kmath.stat -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.misc.sorted import space.kscience.kmath.operations.* import space.kscience.kmath.structures.Buffer @@ -33,7 +33,7 @@ public data class KMComparisonResult>(val n: Int, val m: Int, public fun , A, BA : BufferAlgebra> StatisticalAlgebra.ksComparisonStatistic( x: Buffer, y: Buffer, -): KMComparisonResult where A : Group, A : NumericAlgebra = elementAlgebra.invoke { +): KMComparisonResult where A : Group, A : NumericAlgebra = with(elementAlgebra) { // Copy and sort the sample arrays val sx = x.sorted() val sy = y.sorted() diff --git a/kmath-stat/src/commonTest/kotlin/space/kscience/kmath/series/TestSeries.kt b/kmath-stat/src/commonTest/kotlin/space/kscience/kmath/series/TestSeries.kt new file mode 100644 index 000000000..d83abb3f4 --- /dev/null +++ b/kmath-stat/src/commonTest/kotlin/space/kscience/kmath/series/TestSeries.kt @@ -0,0 +1,28 @@ +/* + * 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.algebra +import space.kscience.kmath.operations.bufferAlgebra +import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.structures.slice +import kotlin.math.PI +import kotlin.test.Test +import kotlin.test.assertEquals + +class TestSeries { + + @Test + fun zip() = 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 s3: Buffer = s1.zip(s2) { l, r -> l + r } //s1 + s2 + + assertEquals(s3.getByOffset(40),s1.getByOffset(40) + s1.getByOffset(20)) + } +} \ No newline at end of file diff --git a/kmath-symja/README.md b/kmath-symja/README.md index a96b0e835..8672c6a71 100644 --- a/kmath-symja/README.md +++ b/kmath-symja/README.md @@ -6,7 +6,7 @@ Symja integration module ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-symja:0.3.1-dev-1`. +The Maven coordinates of this project are `space.kscience:kmath-symja:0.4.0-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-symja:0.3.1-dev-1' + implementation 'space.kscience:kmath-symja:0.4.0-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-symja:0.3.1-dev-1") + implementation("space.kscience:kmath-symja:0.4.0-dev-1") } ``` diff --git a/kmath-tensorflow/README.md b/kmath-tensorflow/README.md index 83f2eb315..a5b48de4d 100644 --- a/kmath-tensorflow/README.md +++ b/kmath-tensorflow/README.md @@ -6,7 +6,7 @@ Google tensorflow connector ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-tensorflow:0.3.1-dev-1`. +The Maven coordinates of this project are `space.kscience:kmath-tensorflow:0.4.0-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-tensorflow:0.3.1-dev-1' + implementation 'space.kscience:kmath-tensorflow:0.4.0-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-tensorflow:0.3.1-dev-1") + implementation("space.kscience:kmath-tensorflow:0.4.0-dev-1") } ``` 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 27a20aafe..41c7c0b68 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 @@ -10,9 +10,9 @@ import org.tensorflow.Output import org.tensorflow.ndarray.NdArray import org.tensorflow.op.core.Constant import org.tensorflow.types.TFloat64 +import space.kscience.kmath.PerformancePitfall +import space.kscience.kmath.UnstableKMathAPI 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.ShapeND import space.kscience.kmath.nd.StructureND 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 bc5fb9616..73b36cd67 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 @@ -17,9 +17,9 @@ import org.tensorflow.op.core.* 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.PerformancePitfall +import space.kscience.kmath.UnsafeKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.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 af754f841..730feede6 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 @@ -6,7 +6,7 @@ package space.kscience.kmath.tensorflow import org.junit.jupiter.api.Test -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.get import space.kscience.kmath.nd.structureND diff --git a/kmath-tensors/README.md b/kmath-tensors/README.md index 4208cd83d..80f751ffe 100644 --- a/kmath-tensors/README.md +++ b/kmath-tensors/README.md @@ -9,7 +9,7 @@ Common linear algebra operations on tensors. ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-tensors:0.3.1-dev-1`. +The Maven coordinates of this project are `space.kscience:kmath-tensors:0.4.0-dev-1`. **Gradle Groovy:** ```groovy @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-tensors:0.3.1-dev-1' + implementation 'space.kscience:kmath-tensors:0.4.0-dev-1' } ``` **Gradle Kotlin DSL:** @@ -30,6 +30,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-tensors:0.3.1-dev-1") + implementation("space.kscience:kmath-tensors:0.4.0-dev-1") } ``` 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 f337a2175..7db91722f 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 @@ -5,7 +5,7 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.nd.StructureND import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.tensors.api.Tensor 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 a7283e4c8..eaec43e2c 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 @@ -5,7 +5,7 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.nd.RowStrides import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.Strides 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 4eed7a2a8..d2c2e9d5d 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,9 +5,10 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.misc.UnstableKMathAPI -import space.kscience.kmath.nd.* +import space.kscience.kmath.PerformancePitfall +import space.kscience.kmath.UnstableKMathAPI +import space.kscience.kmath.nd.MutableStructureNDOfDouble +import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.structures.* import space.kscience.kmath.tensors.core.internal.toPrettyString 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 index e74f73800..d2066e404 100644 --- 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 @@ -5,7 +5,7 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.nd.MutableStructure1D import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.structures.MutableBuffer 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 index 7c84b91e1..fa142afa0 100644 --- 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 @@ -5,7 +5,7 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.nd.MutableStructure2D import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.nd.linearSize 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 997c0a316..70a3ef7e2 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 @@ -8,8 +8,7 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.misc.PerformancePitfall -import space.kscience.kmath.misc.UnstableKMathAPI +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.nd.* import space.kscience.kmath.operations.DoubleBufferOps import space.kscience.kmath.operations.DoubleField @@ -18,7 +17,10 @@ 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.core.internal.* -import kotlin.math.* +import kotlin.math.abs +import kotlin.math.ceil +import kotlin.math.floor +import kotlin.math.sqrt /** * Implementation of basic operations over double tensors and basic algebra operations on them. @@ -349,7 +351,6 @@ public open class DoubleTensorAlgebra : * @param other tensor to be multiplied. * @return a mathematical product of two tensors. */ - @UnstableKMathAPI public infix fun StructureND.matmul(other: StructureND): DoubleTensor { if (shape.size == 1 && other.shape.size == 1) { return DoubleTensor(ShapeND(1), DoubleBuffer(times(other).sum())) @@ -411,7 +412,7 @@ public open class DoubleTensorAlgebra : } override fun StructureND.dot(other: StructureND): DoubleTensor { - return if (dimension in 0..2 && other.dimension in 0..2) matmul(other) + return if (dimension in 0..2 && other.dimension in 0..2) this.matmul(other) else error("Only vectors and matrices are allowed in non-broadcasting dot operation") } 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 a77c4de4c..f028e2cbb 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,7 +5,7 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.nd.ShapeND import space.kscience.kmath.structures.* 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 429b3ffa9..d1cdc68d4 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 @@ -8,7 +8,7 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.nd.* import space.kscience.kmath.operations.IntRing import space.kscience.kmath.structures.* 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 0b0325a85..1e87e6620 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,7 +5,7 @@ package space.kscience.kmath.tensors.core.internal -import space.kscience.kmath.misc.UnsafeKMathAPI +import space.kscience.kmath.UnsafeKMathAPI import space.kscience.kmath.nd.* import space.kscience.kmath.structures.asBuffer import space.kscience.kmath.tensors.core.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 91fcc90ee..2709ac474 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,7 +5,7 @@ package space.kscience.kmath.tensors.core.internal -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.nd.asList import space.kscience.kmath.nd.last import space.kscience.kmath.operations.DoubleBufferOps.Companion.map 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 1733c1a7e..e2b7c23e6 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 @@ -7,7 +7,7 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.nd.ShapeND import kotlin.jvm.JvmName 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 d01ae124b..811fc1117 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 @@ -5,7 +5,7 @@ package space.kscience.kmath.tensors.core -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.nd.* import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.DoubleBuffer @@ -16,6 +16,7 @@ import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue +@OptIn(PerformancePitfall::class) internal class TestDoubleTensor { @Test diff --git a/kmath-viktor/README.md b/kmath-viktor/README.md index abff20427..8a781af4c 100644 --- a/kmath-viktor/README.md +++ b/kmath-viktor/README.md @@ -6,7 +6,7 @@ Binding for https://github.com/JetBrains-Research/viktor ## Artifact: -The Maven coordinates of this project are `space.kscience:kmath-viktor:0.3.1-dev-1`. +The Maven coordinates of this project are `space.kscience:kmath-viktor:0.4.0-dev-1`. **Gradle Groovy:** ```groovy @@ -16,7 +16,7 @@ repositories { } dependencies { - implementation 'space.kscience:kmath-viktor:0.3.1-dev-1' + implementation 'space.kscience:kmath-viktor:0.4.0-dev-1' } ``` **Gradle Kotlin DSL:** @@ -27,6 +27,6 @@ repositories { } dependencies { - implementation("space.kscience:kmath-viktor:0.3.1-dev-1") + implementation("space.kscience:kmath-viktor:0.4.0-dev-1") } ``` 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 8533c9d32..8c7d6d199 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 @@ -8,9 +8,9 @@ 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.PerformancePitfall +import space.kscience.kmath.UnsafeKMathAPI +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.nd.* import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.ExtendedFieldOps 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 085790355..7c0c02086 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 @@ -6,7 +6,7 @@ package space.kscience.kmath.viktor import org.jetbrains.bio.viktor.F64Array -import space.kscience.kmath.misc.PerformancePitfall +import space.kscience.kmath.PerformancePitfall import space.kscience.kmath.nd.ColumnStrides import space.kscience.kmath.nd.MutableStructureND import space.kscience.kmath.nd.ShapeND diff --git a/test-utils/build.gradle.kts b/test-utils/build.gradle.kts index b860a62ec..31c57aca7 100644 --- a/test-utils/build.gradle.kts +++ b/test-utils/build.gradle.kts @@ -6,6 +6,7 @@ kscience{ jvm() js() native() +// wasm() } kotlin.sourceSets { -- 2.34.1 From b2746e5c0ef6c31d89640f6cfe7f41e3c2c74930 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 9 Apr 2023 10:55:58 +0300 Subject: [PATCH 252/275] Wasm support --- CHANGELOG.md | 1 + build.gradle.kts | 14 +-- .../space/kscience/kmath/ast/TypedMst.kt | 5 - .../kscience/kmath/ast/evaluateConstants.kt | 2 - .../ast/rendering/LatexSyntaxRenderer.kt | 3 - .../ast/rendering/MathMLSyntaxRenderer.kt | 3 - .../kmath/ast/rendering/MathRenderer.kt | 4 - .../kmath/ast/rendering/MathSyntax.kt | 25 ----- .../kmath/ast/rendering/SyntaxRenderer.kt | 4 - .../kscience/kmath/ast/rendering/features.kt | 22 ---- .../kscience/kmath/ast/rendering/phases.kt | 5 - kmath-complex/build.gradle.kts | 22 ++++ kmath-core/build.gradle.kts | 22 +++- .../space/kscience/kmath/misc/PermSortTest.kt | 2 + .../kmath/structures/NumberNDFieldTest.kt | 1 + kmath-coroutines/build.gradle.kts | 1 + kmath-functions/build.gradle.kts | 30 +++-- kmath-geometry/build.gradle.kts | 5 + .../kscience/kmath/jupyter/KMathJupyter.kt | 2 + kmath-memory/build.gradle.kts | 18 ++- .../space/kscience/kmath/memory/MemoryTest.kt | 37 +++++++ .../kscience/kmath/memory/ByteBufferMemory.kt | 5 +- .../kmath/memory/WasmDataViewMemory.kt | 103 ++++++++++++++++++ .../space/kscience/kmath/memory/WasmMemory.kt | 66 ----------- .../kmath/optimization/OptimizationBuilder.kt | 3 + kmath-stat/build.gradle.kts | 2 +- test-utils/build.gradle.kts | 2 +- 27 files changed, 242 insertions(+), 167 deletions(-) create mode 100644 kmath-memory/src/commonTest/kotlin/space/kscience/kmath/memory/MemoryTest.kt create mode 100644 kmath-memory/src/wasmMain/kotlin/space/kscience/kmath/memory/WasmDataViewMemory.kt delete mode 100644 kmath-memory/src/wasmMain/kotlin/space/kscience/kmath/memory/WasmMemory.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d4e6123b..08b72f0d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## [Unreleased] ### Added +- Wasm support for `memory`, `core`, `complex` and `functions` modules. - Generic builders for `BufferND` and `MutableBufferND` - `NamedMatrix` - matrix with symbol-based indexing - `Expression` with default arguments diff --git a/build.gradle.kts b/build.gradle.kts index 2eea9c47b..ec67eaa54 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,7 +15,7 @@ allprojects { } group = "space.kscience" - version = "0.4.0-dev-1" + version = "0.3.1-dev-RC" } subprojects { @@ -55,18 +55,6 @@ subprojects { } } } - - plugins.withId("org.jetbrains.kotlin.multiplatform") { - configure { - sourceSets { - val commonTest by getting { - dependencies { - implementation(projects.testUtils) - } - } - } - } - } } readme.readmeTemplate = file("docs/templates/README-TEMPLATE.md") diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/TypedMst.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/TypedMst.kt index e211259af..e82f7a3ab 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/TypedMst.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/TypedMst.kt @@ -5,7 +5,6 @@ package space.kscience.kmath.ast -import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.operations.Algebra @@ -16,7 +15,6 @@ import space.kscience.kmath.operations.NumericAlgebra * * @param T the type. */ -@UnstableKMathAPI public sealed interface TypedMst { /** * A node containing a unary operation. @@ -133,7 +131,6 @@ public sealed interface TypedMst { /** * Interprets the [TypedMst] node with this [Algebra] and [arguments]. */ -@UnstableKMathAPI public fun TypedMst.interpret(algebra: Algebra, arguments: Map): T = when (this) { is TypedMst.Unary -> algebra.unaryOperation(operation, interpret(algebra, arguments)) @@ -158,7 +155,6 @@ public fun TypedMst.interpret(algebra: Algebra, arguments: Map TypedMst.interpret(algebra: Algebra, vararg arguments: Pair): T = interpret( algebra, when (arguments.size) { @@ -171,7 +167,6 @@ public fun TypedMst.interpret(algebra: Algebra, vararg arguments: Pair /** * Interpret this [TypedMst] node as expression. */ -@UnstableKMathAPI public fun TypedMst.toExpression(algebra: Algebra): Expression = Expression { arguments -> interpret(algebra, arguments) } diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/evaluateConstants.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/evaluateConstants.kt index fb0c9b872..8fc5a6aaf 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/evaluateConstants.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/evaluateConstants.kt @@ -5,7 +5,6 @@ package space.kscience.kmath.ast -import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.operations.Algebra @@ -15,7 +14,6 @@ import space.kscience.kmath.operations.bindSymbolOrNull /** * Evaluates constants in given [MST] for given [algebra] at the same time with converting to [TypedMst]. */ -@UnstableKMathAPI public fun MST.evaluateConstants(algebra: Algebra): TypedMst = when (this) { is MST.Numeric -> TypedMst.Constant( (algebra as? NumericAlgebra)?.number(value) ?: error("Numeric nodes are not supported by $algebra"), diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt index 50162a4f5..5a338afed 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/LatexSyntaxRenderer.kt @@ -5,8 +5,6 @@ package space.kscience.kmath.ast.rendering -import space.kscience.kmath.UnstableKMathAPI - /** * [SyntaxRenderer] implementation for LaTeX. * @@ -25,7 +23,6 @@ import space.kscience.kmath.UnstableKMathAPI * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public object LatexSyntaxRenderer : SyntaxRenderer { override fun render(node: MathSyntax, output: Appendable): Unit = output.run { fun render(syntax: MathSyntax) = render(syntax, output) diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt index bb49c5df4..bfd9aeef9 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathMLSyntaxRenderer.kt @@ -5,8 +5,6 @@ package space.kscience.kmath.ast.rendering -import space.kscience.kmath.UnstableKMathAPI - /** * [SyntaxRenderer] implementation for MathML. * @@ -14,7 +12,6 @@ import space.kscience.kmath.UnstableKMathAPI * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public object MathMLSyntaxRenderer : SyntaxRenderer { override fun render(node: MathSyntax, output: Appendable) { output.append("") diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt index afa25febe..f88a5b319 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt @@ -5,7 +5,6 @@ package space.kscience.kmath.ast.rendering -import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.expressions.MST /** @@ -13,7 +12,6 @@ import space.kscience.kmath.expressions.MST * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public fun interface MathRenderer { /** * Renders [MST] to [MathSyntax]. @@ -27,7 +25,6 @@ public fun interface MathRenderer { * @property features The applied features. * @author Iaroslav Postovalov */ -@UnstableKMathAPI public open class FeaturedMathRenderer(public val features: List) : MathRenderer { override fun render(mst: MST): MathSyntax { for (feature in features) feature.render(this, mst)?.let { return it } @@ -51,7 +48,6 @@ public open class FeaturedMathRenderer(public val features: List) * @property stages The applied stages. * @author Iaroslav Postovalov */ -@UnstableKMathAPI public open class FeaturedMathRendererWithPostProcess( features: List, public val stages: List, diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt index 887469164..0196be3b6 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathSyntax.kt @@ -5,14 +5,11 @@ package space.kscience.kmath.ast.rendering -import space.kscience.kmath.UnstableKMathAPI - /** * Syntax node for mathematical typography. * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public sealed class MathSyntax { /** * The parent node of this syntax node. @@ -25,7 +22,6 @@ public sealed class MathSyntax { * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public sealed class TerminalSyntax : MathSyntax() /** @@ -33,7 +29,6 @@ public sealed class TerminalSyntax : MathSyntax() * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public sealed class OperationSyntax : MathSyntax() { /** * The operation token. @@ -46,7 +41,6 @@ public sealed class OperationSyntax : MathSyntax() { * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public sealed class UnarySyntax : OperationSyntax() { /** * The operand of this node. @@ -59,7 +53,6 @@ public sealed class UnarySyntax : OperationSyntax() { * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public sealed class BinarySyntax : OperationSyntax() { /** * The left-hand side operand. @@ -78,7 +71,6 @@ public sealed class BinarySyntax : OperationSyntax() { * @property string The digits of number. * @author Iaroslav Postovalov */ -@UnstableKMathAPI public data class NumberSyntax(public var string: String) : TerminalSyntax() /** @@ -87,7 +79,6 @@ public data class NumberSyntax(public var string: String) : TerminalSyntax() * @property string The symbol. * @author Iaroslav Postovalov */ -@UnstableKMathAPI public data class SymbolSyntax(public var string: String) : TerminalSyntax() /** @@ -98,7 +89,6 @@ public data class SymbolSyntax(public var string: String) : TerminalSyntax() * @see UnaryOperatorSyntax * @author Iaroslav Postovalov */ -@UnstableKMathAPI public data class OperatorNameSyntax(public var name: String) : TerminalSyntax() /** @@ -107,7 +97,6 @@ public data class OperatorNameSyntax(public var name: String) : TerminalSyntax() * @property kind The kind of symbol. * @author Iaroslav Postovalov */ -@UnstableKMathAPI public data class SpecialSymbolSyntax(public var kind: Kind) : TerminalSyntax() { /** * The kind of symbol. @@ -132,7 +121,6 @@ public data class SpecialSymbolSyntax(public var kind: Kind) : TerminalSyntax() * @property parentheses Whether the operand should be wrapped with parentheses. * @author Iaroslav Postovalov */ -@UnstableKMathAPI public data class OperandSyntax( public val operand: MathSyntax, public var parentheses: Boolean, @@ -148,7 +136,6 @@ public data class OperandSyntax( * @property prefix The prefix. * @author Iaroslav Postovalov */ -@UnstableKMathAPI public data class UnaryOperatorSyntax( override val operation: String, public var prefix: MathSyntax, @@ -164,7 +151,6 @@ public data class UnaryOperatorSyntax( * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public data class UnaryPlusSyntax( override val operation: String, override val operand: OperandSyntax, @@ -179,7 +165,6 @@ public data class UnaryPlusSyntax( * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public data class UnaryMinusSyntax( override val operation: String, override val operand: OperandSyntax, @@ -195,7 +180,6 @@ public data class UnaryMinusSyntax( * @property operand The radicand. * @author Iaroslav Postovalov */ -@UnstableKMathAPI public data class RadicalSyntax( override val operation: String, override val operand: MathSyntax, @@ -213,7 +197,6 @@ public data class RadicalSyntax( * (*ex*). * @author Iaroslav Postovalov */ -@UnstableKMathAPI public data class ExponentSyntax( override val operation: String, override val operand: OperandSyntax, @@ -231,7 +214,6 @@ public data class ExponentSyntax( * @property right The superscript. * @author Iaroslav Postovalov */ -@UnstableKMathAPI public data class SuperscriptSyntax( override val operation: String, override val left: MathSyntax, @@ -250,7 +232,6 @@ public data class SuperscriptSyntax( * @property right The subscript. * @author Iaroslav Postovalov */ -@UnstableKMathAPI public data class SubscriptSyntax( override val operation: String, override val left: MathSyntax, @@ -268,7 +249,6 @@ public data class SubscriptSyntax( * @property prefix The prefix. * @author Iaroslav Postovalov */ -@UnstableKMathAPI public data class BinaryOperatorSyntax( override val operation: String, public var prefix: MathSyntax, @@ -288,7 +268,6 @@ public data class BinaryOperatorSyntax( * @param right The addend. * @author Iaroslav Postovalov */ -@UnstableKMathAPI public data class BinaryPlusSyntax( override val operation: String, override val left: OperandSyntax, @@ -307,7 +286,6 @@ public data class BinaryPlusSyntax( * @param right The subtrahend. * @author Iaroslav Postovalov */ -@UnstableKMathAPI public data class BinaryMinusSyntax( override val operation: String, override val left: OperandSyntax, @@ -327,7 +305,6 @@ public data class BinaryMinusSyntax( * @property infix Whether infix (*1 / 2*) or normal (*½*) fraction should be made. * @author Iaroslav Postovalov */ -@UnstableKMathAPI public data class FractionSyntax( override val operation: String, override val left: OperandSyntax, @@ -347,7 +324,6 @@ public data class FractionSyntax( * @property right The radicand. * @author Iaroslav Postovalov */ -@UnstableKMathAPI public data class RadicalWithIndexSyntax( override val operation: String, override val left: MathSyntax, @@ -367,7 +343,6 @@ public data class RadicalWithIndexSyntax( * @property times Whether the times (×) symbol should be used. * @author Iaroslav Postovalov */ -@UnstableKMathAPI public data class MultiplicationSyntax( override val operation: String, override val left: OperandSyntax, diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt index 7669be664..16957bdd2 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/SyntaxRenderer.kt @@ -5,15 +5,12 @@ package space.kscience.kmath.ast.rendering -import space.kscience.kmath.UnstableKMathAPI - /** * Abstraction of writing [MathSyntax] as a string of an actual markup language. Typical implementation should * involve traversal of MathSyntax with handling each subtype. * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public fun interface SyntaxRenderer { /** * Renders the [MathSyntax] to [output]. @@ -26,7 +23,6 @@ public fun interface SyntaxRenderer { * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public fun SyntaxRenderer.renderWithStringBuilder(node: MathSyntax): String { val sb = StringBuilder() render(node, sb) diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt index 8bb7e3585..4deffc83c 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/features.kt @@ -5,7 +5,6 @@ package space.kscience.kmath.ast.rendering -import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.ast.rendering.FeaturedMathRenderer.RenderFeature import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.Symbol @@ -17,7 +16,6 @@ import kotlin.reflect.KClass * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public val PrintSymbol: RenderFeature = RenderFeature { _, node -> if (node !is Symbol) null else SymbolSyntax(string = node.identity) @@ -28,7 +26,6 @@ public val PrintSymbol: RenderFeature = RenderFeature { _, node -> * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public val PrintNumeric: RenderFeature = RenderFeature { _, node -> if (node !is MST.Numeric) null @@ -36,7 +33,6 @@ public val PrintNumeric: RenderFeature = RenderFeature { _, node -> NumberSyntax(string = node.value.toString()) } -@UnstableKMathAPI private fun printSignedNumberString(s: String): MathSyntax = if (s.startsWith('-')) UnaryMinusSyntax( operation = GroupOps.MINUS_OPERATION, @@ -55,7 +51,6 @@ else * @property types The suitable types. * @author Iaroslav Postovalov */ -@UnstableKMathAPI public class PrettyPrintFloats(public val types: Set>) : RenderFeature { override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? { if (node !is MST.Numeric || node.value::class !in types) return null @@ -115,7 +110,6 @@ public class PrettyPrintFloats(public val types: Set>) : Rend * @property types The suitable types. * @author Iaroslav Postovalov */ -@UnstableKMathAPI public class PrettyPrintIntegers(public val types: Set>) : RenderFeature { override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? = if (node !is MST.Numeric || node.value::class !in types) @@ -138,7 +132,6 @@ public class PrettyPrintIntegers(public val types: Set>) : Re * @property symbols The allowed symbols. * @author Iaroslav Postovalov */ -@UnstableKMathAPI public class PrettyPrintPi(public val symbols: Set) : RenderFeature { override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? = if (node !is Symbol || node.identity !in symbols) @@ -161,7 +154,6 @@ public class PrettyPrintPi(public val symbols: Set) : RenderFeature { * @param operations the allowed operations. If `null`, any operation is accepted. * @author Iaroslav Postovalov */ -@UnstableKMathAPI public abstract class Unary(public val operations: Collection?) : RenderFeature { /** * The actual render function specialized for [MST.Unary]. @@ -182,7 +174,6 @@ public abstract class Unary(public val operations: Collection?) : Render * @property operations the allowed operations. If `null`, any operation is accepted. * @author Iaroslav Postovalov */ -@UnstableKMathAPI public abstract class Binary(public val operations: Collection?) : RenderFeature { /** * The actual render function specialized for [MST.Binary]. @@ -200,7 +191,6 @@ public abstract class Binary(public val operations: Collection?) : Rende * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public class BinaryPlus(operations: Collection?) : Binary(operations) { override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryPlusSyntax( @@ -222,7 +212,6 @@ public class BinaryPlus(operations: Collection?) : Binary(operations) { * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public class BinaryMinus(operations: Collection?) : Binary(operations) { override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryMinusSyntax( @@ -244,7 +233,6 @@ public class BinaryMinus(operations: Collection?) : Binary(operations) { * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public class UnaryPlus(operations: Collection?) : Unary(operations) { override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryPlusSyntax( operation = node.operation, @@ -264,7 +252,6 @@ public class UnaryPlus(operations: Collection?) : Unary(operations) { * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public class UnaryMinus(operations: Collection?) : Unary(operations) { override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryMinusSyntax( operation = node.operation, @@ -284,7 +271,6 @@ public class UnaryMinus(operations: Collection?) : Unary(operations) { * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public class Fraction(operations: Collection?) : Binary(operations) { override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = FractionSyntax( operation = node.operation, @@ -306,7 +292,6 @@ public class Fraction(operations: Collection?) : Binary(operations) { * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public class BinaryOperator(operations: Collection?) : Binary(operations) { override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = BinaryOperatorSyntax( @@ -329,7 +314,6 @@ public class BinaryOperator(operations: Collection?) : Binary(operations * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public class UnaryOperator(operations: Collection?) : Unary(operations) { override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryOperatorSyntax( @@ -351,7 +335,6 @@ public class UnaryOperator(operations: Collection?) : Unary(operations) * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public class Power(operations: Collection?) : Binary(operations) { override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = SuperscriptSyntax( @@ -371,7 +354,6 @@ public class Power(operations: Collection?) : Binary(operations) { /** * Handles binary nodes by producing [RadicalSyntax] with no index. */ -@UnstableKMathAPI public class SquareRoot(operations: Collection?) : Unary(operations) { override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = RadicalSyntax(operation = node.operation, operand = parent.render(node.value)) @@ -389,7 +371,6 @@ public class SquareRoot(operations: Collection?) : Unary(operations) { * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public class Exponent(operations: Collection?) : Unary(operations) { override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = ExponentSyntax( operation = node.operation, @@ -410,7 +391,6 @@ public class Exponent(operations: Collection?) : Unary(operations) { * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public class Multiplication(operations: Collection?) : Binary(operations) { override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = MultiplicationSyntax( @@ -433,7 +413,6 @@ public class Multiplication(operations: Collection?) : Binary(operations * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public class InverseTrigonometricOperations(operations: Collection?) : Unary(operations) { override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryOperatorSyntax( @@ -460,7 +439,6 @@ public class InverseTrigonometricOperations(operations: Collection?) : U * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public class InverseHyperbolicOperations(operations: Collection?) : Unary(operations) { override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryOperatorSyntax( diff --git a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt index 2399e8f68..0d26621d3 100644 --- a/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt +++ b/kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/rendering/phases.kt @@ -5,7 +5,6 @@ package space.kscience.kmath.ast.rendering -import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.ast.rendering.FeaturedMathRendererWithPostProcess.PostProcessPhase import space.kscience.kmath.operations.FieldOps import space.kscience.kmath.operations.GroupOps @@ -17,7 +16,6 @@ import space.kscience.kmath.operations.RingOps * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public val BetterMultiplication: PostProcessPhase = PostProcessPhase { node -> fun perform(node: MathSyntax): Unit = when (node) { is NumberSyntax -> Unit @@ -91,7 +89,6 @@ public val BetterMultiplication: PostProcessPhase = PostProcessPhase { node -> * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public val BetterFraction: PostProcessPhase = PostProcessPhase { node -> fun perform(node: MathSyntax, infix: Boolean = false): Unit = when (node) { is NumberSyntax -> Unit @@ -162,7 +159,6 @@ public val BetterFraction: PostProcessPhase = PostProcessPhase { node -> * * @author Iaroslav Postovalov */ -@UnstableKMathAPI public val BetterExponent: PostProcessPhase = PostProcessPhase { node -> fun perform(node: MathSyntax): Boolean { return when (node) { @@ -202,7 +198,6 @@ public val BetterExponent: PostProcessPhase = PostProcessPhase { node -> * @property precedenceFunction Returns the precedence number for syntax node. Higher number is lower priority. * @author Iaroslav Postovalov */ -@UnstableKMathAPI public class SimplifyParentheses(public val precedenceFunction: (MathSyntax) -> Int) : PostProcessPhase { override fun perform(node: MathSyntax): Unit = when (node) { diff --git a/kmath-complex/build.gradle.kts b/kmath-complex/build.gradle.kts index 76d5a4c9a..0611e9aae 100644 --- a/kmath-complex/build.gradle.kts +++ b/kmath-complex/build.gradle.kts @@ -7,9 +7,31 @@ kscience { js() native() + wasm{ + browser { + testTask { + useKarma { + this.webpackConfig.experiments.add("topLevelAwait") + useChromeHeadless() + useConfigDirectory(project.projectDir.resolve("karma.config.d").resolve("wasm")) + } + } + } + } + + wasmTest{ + dependencies { + implementation(kotlin("test")) + } + } + dependencies { api(projects.kmathCore) } + + testDependencies { + implementation(projects.testUtils) + } } readme { diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index b6a955b12..08411be59 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -6,11 +6,31 @@ kscience{ jvm() js() native() -// wasm() + wasm{ + browser { + testTask { + useKarma { + this.webpackConfig.experiments.add("topLevelAwait") + useChromeHeadless() + useConfigDirectory(project.projectDir.resolve("karma.config.d").resolve("wasm")) + } + } + } + } + + wasmTest{ + dependencies { + implementation(kotlin("test")) + } + } dependencies { api(projects.kmathMemory) } + + testDependencies { + implementation(projects.testUtils) + } } kotlin.sourceSets { diff --git a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/misc/PermSortTest.kt b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/misc/PermSortTest.kt index 4f3469ea2..dd97df1e8 100644 --- a/kmath-core/src/commonTest/kotlin/space/kscience/kmath/misc/PermSortTest.kt +++ b/kmath-core/src/commonTest/kotlin/space/kscience/kmath/misc/PermSortTest.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.misc +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.misc.PermSortTest.Platform.* import space.kscience.kmath.structures.IntBuffer import space.kscience.kmath.structures.asBuffer @@ -14,6 +15,7 @@ import kotlin.test.assertContentEquals import kotlin.test.assertEquals import kotlin.test.assertTrue +@OptIn(UnstableKMathAPI::class) class PermSortTest { private enum class Platform { 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 1572db816..993fb089f 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 @@ -22,6 +22,7 @@ import kotlin.math.pow import kotlin.test.Test import kotlin.test.assertEquals +@OptIn(PerformancePitfall::class) @Suppress("UNUSED_VARIABLE") class NumberNDFieldTest { val algebra = DoubleField.ndAlgebra diff --git a/kmath-coroutines/build.gradle.kts b/kmath-coroutines/build.gradle.kts index 9d5cfabe4..1e901ca98 100644 --- a/kmath-coroutines/build.gradle.kts +++ b/kmath-coroutines/build.gradle.kts @@ -6,6 +6,7 @@ kscience { jvm() js() native() + dependencies { api(project(":kmath-core")) api(project(":kmath-complex")) diff --git a/kmath-functions/build.gradle.kts b/kmath-functions/build.gradle.kts index 08e76aef0..acabd1eb9 100644 --- a/kmath-functions/build.gradle.kts +++ b/kmath-functions/build.gradle.kts @@ -6,18 +6,32 @@ kscience{ jvm() js() native() + + wasm{ + browser { + testTask { + useKarma { + this.webpackConfig.experiments.add("topLevelAwait") + useChromeHeadless() + useConfigDirectory(project.projectDir.resolve("karma.config.d").resolve("wasm")) + } + } + } + } + + wasmTest{ + dependencies { + implementation(kotlin("test")) + } + } + + dependencies { + api(projects.kmathCore) + } } description = "Functions, integration and interpolation" -kotlin.sourceSets { - commonMain { - dependencies { - api(project(":kmath-core")) - } - } -} - dependencies { dokkaPlugin("org.jetbrains.dokka:mathjax-plugin:${spclibs.versions.dokka.get()}") } diff --git a/kmath-geometry/build.gradle.kts b/kmath-geometry/build.gradle.kts index f248a1717..32926db7e 100644 --- a/kmath-geometry/build.gradle.kts +++ b/kmath-geometry/build.gradle.kts @@ -12,6 +12,11 @@ kscience{ dependencies{ api(projects.kmath.kmathComplex) } + + testDependencies { + implementation(projects.testUtils) + } + } readme { 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 2d32dd609..944666c9e 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 @@ -13,6 +13,7 @@ import org.jetbrains.kotlinx.jupyter.api.DisplayResult import org.jetbrains.kotlinx.jupyter.api.HTML import org.jetbrains.kotlinx.jupyter.api.libraries.JupyterIntegration import space.kscience.kmath.PerformancePitfall +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.ast.rendering.FeaturedMathRendererWithPostProcess import space.kscience.kmath.ast.rendering.MathMLSyntaxRenderer import space.kscience.kmath.ast.rendering.renderWithStringBuilder @@ -30,6 +31,7 @@ import space.kscience.kmath.structures.Buffer */ public fun Number.toMst(): MST.Numeric = MST.Numeric(this) +@OptIn(UnstableKMathAPI::class) internal class KMathJupyter : JupyterIntegration() { private val mathRender = FeaturedMathRendererWithPostProcess.Default private val syntaxRender = MathMLSyntaxRenderer diff --git a/kmath-memory/build.gradle.kts b/kmath-memory/build.gradle.kts index d8af1e3a2..4e5370c0f 100644 --- a/kmath-memory/build.gradle.kts +++ b/kmath-memory/build.gradle.kts @@ -6,7 +6,23 @@ kscience { jvm() js() native() -// wasm() + wasm{ + browser { + testTask { + useKarma { + this.webpackConfig.experiments.add("topLevelAwait") + useChromeHeadless() + useConfigDirectory(project.projectDir.resolve("karma.config.d").resolve("wasm")) + } + } + } + } + + wasmTest{ + dependencies { + implementation(kotlin("test")) + } + } } readme { diff --git a/kmath-memory/src/commonTest/kotlin/space/kscience/kmath/memory/MemoryTest.kt b/kmath-memory/src/commonTest/kotlin/space/kscience/kmath/memory/MemoryTest.kt new file mode 100644 index 000000000..3726ddbb7 --- /dev/null +++ b/kmath-memory/src/commonTest/kotlin/space/kscience/kmath/memory/MemoryTest.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. + */ + +package space.kscience.kmath.memory + +import kotlin.test.Test +import kotlin.test.assertEquals + +class MemoryTest { + @Test + fun memoryWriteRead() { + val memorySize = 60 + val data = buildList { + for (i in 0 until (memorySize / 4)) { + add(i) + } + } + val memory = Memory.allocate(memorySize) + memory.write { + for (i in 0 until (memory.size / 4)) { + writeInt(i*4, data[i]) + } + } + + val result = memory.read { + buildList { + for (i in 0 until (memory.size / 4)) { + add(readInt(i*4)) + } + } + } + + assertEquals(data,result) + } +} \ No newline at end of file diff --git a/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt b/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt index 19910a396..d022cab23 100644 --- a/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt +++ b/kmath-memory/src/jvmMain/kotlin/space/kscience/kmath/memory/ByteBufferMemory.kt @@ -20,8 +20,7 @@ internal class ByteBufferMemory( val startOffset: Int = 0, override val size: Int = buffer.limit(), ) : Memory { - @Suppress("NOTHING_TO_INLINE") - private inline fun position(o: Int): Int = startOffset + o + private fun position(offset: Int): Int = startOffset + offset override fun view(offset: Int, length: Int): Memory { require(offset >= 0) { "offset shouldn't be negative: $offset" } @@ -120,7 +119,7 @@ public fun ByteBuffer.asMemory(startOffset: Int = 0, size: Int = limit()): Memor ByteBufferMemory(this, startOffset, size) /** - * Uses direct memory-mapped buffer from file to read something and close it afterwards. + * Uses direct memory-mapped buffer from file to read something and close it afterward. */ @Throws(IOException::class) public inline fun Path.readAsMemory(position: Long = 0, size: Long = Files.size(this), block: Memory.() -> R): R { diff --git a/kmath-memory/src/wasmMain/kotlin/space/kscience/kmath/memory/WasmDataViewMemory.kt b/kmath-memory/src/wasmMain/kotlin/space/kscience/kmath/memory/WasmDataViewMemory.kt new file mode 100644 index 000000000..0cff551fa --- /dev/null +++ b/kmath-memory/src/wasmMain/kotlin/space/kscience/kmath/memory/WasmDataViewMemory.kt @@ -0,0 +1,103 @@ +/* + * Copyright 2018-2022 KMath 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.memory + +import org.khronos.webgl.ArrayBuffer +import org.khronos.webgl.DataView +import org.khronos.webgl.Int8Array + +private class WasmDataViewMemory(val view: DataView) : Memory { + override val size: Int get() = view.byteLength + + override fun view(offset: Int, length: Int): Memory { + require(offset >= 0) { "offset shouldn't be negative: $offset" } + require(length >= 0) { "length shouldn't be negative: $length" } + require(offset + length <= size) { "Can't view memory outside the parent region." } + + if (offset + length > size) + throw IndexOutOfBoundsException("offset + length > size: $offset + $length > $size") + + return WasmDataViewMemory(DataView(view.buffer, view.byteOffset + offset, length)) + } + + override fun copy(): Memory = WasmDataViewMemory(DataView(view.buffer.slice(0))) + + private val reader: MemoryReader = object : MemoryReader { + override val memory: Memory get() = this@WasmDataViewMemory + + override fun readDouble(offset: Int): Double = view.getFloat64(offset, false) + + override fun readFloat(offset: Int): Float = view.getFloat32(offset, false) + + override fun readByte(offset: Int): Byte = view.getInt8(offset) + + override fun readShort(offset: Int): Short = view.getInt16(offset, false) + + override fun readInt(offset: Int): Int = view.getInt32(offset, false) + + override fun readLong(offset: Int): Long = + view.getInt32(offset, false).toLong() shl 32 or view.getInt32(offset + 4, false).toLong() + + override fun close() { + // does nothing on JS + } + } + + override fun reader(): MemoryReader = reader + + private val writer: MemoryWriter = object : MemoryWriter { + override val memory: Memory get() = this@WasmDataViewMemory + + override fun writeDouble(offset: Int, value: Double) { + view.setFloat64(offset, value, false) + } + + override fun writeFloat(offset: Int, value: Float) { + view.setFloat32(offset, value, false) + } + + override fun writeByte(offset: Int, value: Byte) { + view.setInt8(offset, value) + } + + override fun writeShort(offset: Int, value: Short) { + view.setUint16(offset, value, false) + } + + override fun writeInt(offset: Int, value: Int) { + view.setInt32(offset, value, false) + } + + override fun writeLong(offset: Int, value: Long) { + view.setInt32(offset, (value shr 32).toInt(), littleEndian = false) + view.setInt32(offset + 4, (value and 0xffffffffL).toInt(), littleEndian = false) + } + + override fun close() { + // does nothing on JS + } + } + + override fun writer(): MemoryWriter = writer + +} + +/** + * Allocates memory based on a [DataView]. + */ +public actual fun Memory.Companion.allocate(length: Int): Memory { + val buffer = ArrayBuffer(length) + return WasmDataViewMemory(DataView(buffer, 0, length)) +} + +/** + * Wraps a [Memory] around existing [ByteArray]. This operation is unsafe since the array is not copied + * and could be mutated independently of the resulting [Memory]. + */ +public actual fun Memory.Companion.wrap(array: ByteArray): Memory { + @Suppress("CAST_NEVER_SUCCEEDS") val int8Array = array as Int8Array + return WasmDataViewMemory(DataView(int8Array.buffer, int8Array.byteOffset, int8Array.length)) +} diff --git a/kmath-memory/src/wasmMain/kotlin/space/kscience/kmath/memory/WasmMemory.kt b/kmath-memory/src/wasmMain/kotlin/space/kscience/kmath/memory/WasmMemory.kt deleted file mode 100644 index 7c2be19cc..000000000 --- a/kmath-memory/src/wasmMain/kotlin/space/kscience/kmath/memory/WasmMemory.kt +++ /dev/null @@ -1,66 +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.memory - -import kotlin.wasm.unsafe.Pointer -import kotlin.wasm.unsafe.UnsafeWasmMemoryApi - -@OptIn(UnsafeWasmMemoryApi::class) -public class WasmMemory private constructor( - public val pointer: Pointer, - override val size: Int, -) : Memory { - - override fun view(offset: Int, length: Int): Memory { - TODO("Not yet implemented") - } - - override fun copy(): Memory { - TODO("Not yet implemented") - } - - override fun reader(): MemoryReader = object : MemoryReader { - override val memory: Memory - get() = this@WasmMemory - - override fun readDouble(offset: Int): Double { - return Double.fromBits(pointer.plus(offset).loadLong()) - } - - override fun readFloat(offset: Int): Float { - return Float.fromBits(pointer.plus(offset).loadInt()) - } - - override fun readByte(offset: Int): Byte { - return pointer.plus(offset).loadByte() - } - - override fun readShort(offset: Int): Short { - return pointer.plus(offset).loadShort() - } - - override fun readInt(offset: Int): Int { - return pointer.plus(offset).loadInt() - } - - override fun readLong(offset: Int): Long { - return pointer.plus(offset).loadLong() - } - - override fun close() { - TODO() - } - - } - - override fun writer(): MemoryWriter = TODO() -} - -public actual fun Memory.Companion.allocate(length: Int): Memory { - TODO() -} - -public actual fun Memory.Companion.wrap(array: ByteArray): Memory = TODO() \ No newline at end of file diff --git a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/OptimizationBuilder.kt b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/OptimizationBuilder.kt index d1ceccf1a..0459d46ee 100644 --- a/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/OptimizationBuilder.kt +++ b/kmath-optimization/src/commonMain/kotlin/space/kscience/kmath/optimization/OptimizationBuilder.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.optimization +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.data.XYColumnarData import space.kscience.kmath.expressions.DifferentiableExpression import space.kscience.kmath.expressions.Symbol @@ -69,6 +70,7 @@ public suspend fun DifferentiableExpression.optimizeWith( } +@OptIn(UnstableKMathAPI::class) public class XYOptimizationBuilder( public val data: XYColumnarData, public val model: DifferentiableExpression, @@ -86,6 +88,7 @@ public class XYOptimizationBuilder( ) } +@OptIn(UnstableKMathAPI::class) public fun XYOptimization( data: XYColumnarData, model: DifferentiableExpression, diff --git a/kmath-stat/build.gradle.kts b/kmath-stat/build.gradle.kts index 1426e913a..000280def 100644 --- a/kmath-stat/build.gradle.kts +++ b/kmath-stat/build.gradle.kts @@ -11,7 +11,7 @@ kscience{ kotlin.sourceSets { commonMain { dependencies { - api(project(":kmath-coroutines")) + api(projects.kmathCoroutines) //implementation(spclibs.atomicfu) } } diff --git a/test-utils/build.gradle.kts b/test-utils/build.gradle.kts index 31c57aca7..b03059eaf 100644 --- a/test-utils/build.gradle.kts +++ b/test-utils/build.gradle.kts @@ -6,7 +6,7 @@ kscience{ jvm() js() native() -// wasm() + wasm() } kotlin.sourceSets { -- 2.34.1 From 8ac7567afdd5c94526bf12b153d5fdf11b2a6b60 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 9 Apr 2023 11:08:39 +0300 Subject: [PATCH 253/275] Patch changelog --- CHANGELOG.md | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08b72f0d0..e42fe61f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,27 @@ # KMath -## [Unreleased] +## Unreleased + +### Added + +### Changed + +### Deprecated + +### Removed + +### Fixed + +### Security + +## 0.3.1-dev-RC - 2023-04-09 + ### Added - Wasm support for `memory`, `core`, `complex` and `functions` modules. - Generic builders for `BufferND` and `MutableBufferND` - `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! - Algebra now has an obligatory `bufferFactory` (#477). @@ -17,22 +31,17 @@ - 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 +- Kotlin 1.8.20 - `LazyStructure` `deffered` -> `async` to comply with coroutines code style - Default `dot` operation in tensor algebra no longer support broadcasting. Instead `matmul` operation is added to `DoubleTensorAlgebra`. - Multik went MPP -### Deprecated - ### Removed - Trajectory moved to https://github.com/SciProgCentre/maps-kt - Polynomials moved to https://github.com/SciProgCentre/kmath-polynomial -### Fixed +## 0.3.0 -### Security - -## [0.3.0] ### Added - `ScaleOperations` interface - `Field` extends `ScaleOperations` @@ -57,9 +66,8 @@ - `contentEquals` with tolerance: #364 - Compilation to TeX for MST: #254 - ### Changed -- Annotations moved to `space.kscience.kmath` +- Annotations moved to `space.kscience.kmath` - Exponential operations merged with hyperbolic functions - Space is replaced by Group. Space is reserved for vector spaces. - VectorSpace is now a vector space @@ -91,11 +99,9 @@ - Rework of histograms. - `UnivariateFunction` -> `Function1D`, `MultivariateFunction` -> `FunctionND` - ### Deprecated - Specialized `DoubleBufferAlgebra` - ### Removed - Nearest in Domain. To be implemented in geometry package. - Number multiplication and division in main Algebra chain @@ -106,15 +112,12 @@ - Second generic from DifferentiableExpression - Algebra elements are completely removed. Use algebra contexts instead. - ### Fixed - Ring inherits RingOperations, not GroupOperations - Univariate histogram filling +## 0.2.0 -### Security - -## [0.2.0] ### Added - `fun` annotation for SAM interfaces in library - Explicit `public` visibility for all public APIs @@ -134,7 +137,6 @@ - New `MatrixFeature` interfaces for matrix decompositions - Basic Quaternion vector support in `kmath-complex`. - ### Changed - Package changed from `scientifik` to `space.kscience` - Gradle version: 6.6 -> 6.8.2 @@ -159,7 +161,6 @@ - `symbol` method in `Algebra` renamed to `bindSymbol` to avoid ambiguity - Add `out` projection to `Buffer` generic - ### Removed - `kmath-koma` module because it doesn't support Kotlin 1.4. - Support of `legacy` JS backend (we will support only IR) @@ -168,11 +169,11 @@ - `Real` class - StructureND identity and equals - ### Fixed - `symbol` method in `MstExtendedField` (https://github.com/mipt-npm/kmath/pull/140) -## [0.1.4] +## 0.1.4 + ### Added - Functional Expressions API - Mathematical Syntax Tree, its interpreter and API @@ -190,7 +191,6 @@ - Full hyperbolic functions support and default implementations within `ExtendedField` - Norm support for `Complex` - ### Changed - `readAsMemory` now has `throws IOException` in JVM signature. - Several functions taking functional types were made `inline`. @@ -202,10 +202,9 @@ - Gradle version: 6.3 -> 6.6 - Moved probability distributions to commons-rng and to `kmath-prob` - ### Fixed - Missing copy method in Memory implementation on JS (https://github.com/mipt-npm/kmath/pull/106) - D3.dim value in `kmath-dimensions` - Multiplication in integer rings in `kmath-core` (https://github.com/mipt-npm/kmath/pull/101) - Commons RNG compatibility (https://github.com/mipt-npm/kmath/issues/93) -- Multiplication of BigInt by scalar \ No newline at end of file +- Multiplication of BigInt by scalar -- 2.34.1 From e1d5409c0d1148b2ba9e8221d09cb514c22e7fb9 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 9 Apr 2023 11:12:04 +0300 Subject: [PATCH 254/275] Patch changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e42fe61f3..998e6daae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,7 +26,7 @@ - Algebra now has an obligatory `bufferFactory` (#477). ### Changed -- Trajectory use type-safe angles +- Geometry uses type-safe angles - Tensor operations switched to prefix notation - Row-wise and column-wise ND shapes in the core - Shape is read-only -- 2.34.1 From 31d1cc774af7ce56a8d401691ecb08e9a24a2b1c Mon Sep 17 00:00:00 2001 From: mrFendel Date: Tue, 11 Apr 2023 20:31:04 +0300 Subject: [PATCH 255/275] added shiftOperartion and diff --- .../space/kscience/kmath/series/SeriesAlgebra.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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 3ccbca5a1..4b7f8b83a 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 @@ -199,12 +199,25 @@ public open class SeriesAlgebra, out BA : BufferAlgebra } } + /** + * Zip buffer with itself, but shifted + * */ + public inline fun Buffer.shiftOp( + shift: Int = 1, + crossinline operation: A.(left: T, right: T) -> T + ): Buffer { + val shifted = this.moveTo(this.startOffset+shift) + return zip(shifted, operation) + } + 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 inline fun Buffer.diff(): Buffer = this.shiftOp {l, r -> r - l} + public companion object } -- 2.34.1 From e76d8e0774c2e3fe4a194e81403790d2850f4193 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 12 Apr 2023 11:40:27 +0300 Subject: [PATCH 256/275] fix zipWithNextCircular on single element --- .../kotlin/space/kscience/kmath/misc/collections.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 index afa76d2a9..f630055fa 100644 --- a/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/collections.kt +++ b/kmath-core/src/commonMain/kotlin/space/kscience/kmath/misc/collections.kt @@ -9,7 +9,7 @@ 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() + if (size < 2) return emptyList() return indices.map { i -> if (i == size - 1) { transform(last(), first()) @@ -19,4 +19,4 @@ public inline fun List.zipWithNextCircular(transform: (a: T, b: T) -> } } -public fun List.zipWithNextCircular(): List> = zipWithNextCircular { l, r -> l to r } \ No newline at end of file +public fun List.zipWithNextCircular(): List> = zipWithNextCircular { l, r -> l to r } \ No newline at end of file -- 2.34.1 From 2b83560da8ff62b58d0df8bb334a76f3db3ccf09 Mon Sep 17 00:00:00 2001 From: mrFendel Date: Wed, 12 Apr 2023 22:24:48 +0300 Subject: [PATCH 257/275] Variance Ratio function --- .../kscience/kmath/series/VarianceRatio.kt | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatio.kt diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatio.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatio.kt new file mode 100644 index 000000000..aa616487b --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatio.kt @@ -0,0 +1,30 @@ +/* + * 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.DoubleBufferOps.Companion.map +import space.kscience.kmath.operations.algebra +import space.kscience.kmath.operations.bufferAlgebra +import space.kscience.kmath.operations.fold + + +fun varianceRatio(series: Series, shift: Int): Double { + val mean = series.fold(0.0) {acc, value -> acc + value} / series.size + val demeanedSquares = series.map { power(it - mean, 2) } + val variance = demeanedSquares.fold(0.0) {acc, value -> acc + value} + + with(Double.algebra.bufferAlgebra.seriesAlgebra()) { + val seriesAgg = series + for (i in -1..-shift + 1) { + seriesAgg.shiftOp(i) { v1, v2 -> v1 + v2 } + } + + val demeanedSquaresAgg = seriesAgg.map { power(it - shift * mean, 2) } + val varianceAgg = demeanedSquaresAgg.fold(0.0) { acc, value -> acc + value } + + return varianceAgg * (series.size - 1) / variance / (series.size - shift + 1) / (1 - shift / series.size) + } +} -- 2.34.1 From a68ebef26dda77e015c1d8144999c40083ee303f Mon Sep 17 00:00:00 2001 From: mrFendel Date: Thu, 13 Apr 2023 03:38:10 +0300 Subject: [PATCH 258/275] zScore for variance Ratio Test --- .../kscience/kmath/series/VarianceRatio.kt | 42 ++++++++++++++----- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatio.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatio.kt index aa616487b..2dfcd6b00 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatio.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatio.kt @@ -5,26 +5,48 @@ package space.kscience.kmath.series +import space.kscience.kmath.distributions.NormalDistribution import space.kscience.kmath.operations.DoubleBufferOps.Companion.map +import space.kscience.kmath.operations.DoubleField.pow import space.kscience.kmath.operations.algebra import space.kscience.kmath.operations.bufferAlgebra import space.kscience.kmath.operations.fold -fun varianceRatio(series: Series, shift: Int): Double { - val mean = series.fold(0.0) {acc, value -> acc + value} / series.size +// TODO: add p-value +public data class VarianceRatioTestResult(val varianceRatio: Double, val zScore: Double) + +public fun varianceRatioTest(series: Series, shift: Int, homoscedastic: Boolean): VarianceRatioTestResult { + + val sum = { x: Double, y: Double -> x + y } + + val mean = series.fold(0.0, sum) / series.size val demeanedSquares = series.map { power(it - mean, 2) } - val variance = demeanedSquares.fold(0.0) {acc, value -> acc + value} + val variance = demeanedSquares.fold(0.0, sum) with(Double.algebra.bufferAlgebra.seriesAlgebra()) { - val seriesAgg = series - for (i in -1..-shift + 1) { - seriesAgg.shiftOp(i) { v1, v2 -> v1 + v2 } + for (i in -1..-shift + 1) { series.shiftOp(i) { v1, v2 -> v1 + v2 } } + val demeanedSquaresAgg = series.map { power(it - shift * mean, 2) } + val varianceAgg = demeanedSquaresAgg.fold(0.0, sum) + + val varianceRatio = + varianceAgg * (series.size - 1) / variance / (series.size - shift + 1) / (1 - shift / series.size) + + + // calculating asymptotic variance + var phi: Double + if (homoscedastic) { // under homoscedastic null hypothesis + phi = 2 * (2 * shift - 1.0) * (shift - 1.0) / (3 * shift * series.size) + } else { // under homoscedastic null hypothesis + phi = 0.0 + for (j in 1.. v1 * v2 } + val delta = series.size * shiftedProd.fold(0.0, sum) / variance.pow(2) + phi += delta * 4 * (shift - j) * (shift - j) / shift / shift // TODO: refactor with square + } } - val demeanedSquaresAgg = seriesAgg.map { power(it - shift * mean, 2) } - val varianceAgg = demeanedSquaresAgg.fold(0.0) { acc, value -> acc + value } - - return varianceAgg * (series.size - 1) / variance / (series.size - shift + 1) / (1 - shift / series.size) + val zScore = (varianceRatio - 1) / phi.pow(0.5) + return VarianceRatioTestResult(varianceRatio, zScore) } } -- 2.34.1 From 0ce1861ab4724912e796ffa92aa940fdaa0735a0 Mon Sep 17 00:00:00 2001 From: mrFendel Date: Thu, 13 Apr 2023 03:47:36 +0300 Subject: [PATCH 259/275] refactoring --- .../series/{VarianceRatio.kt => VarianceRatioTest.kt} | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) rename kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/{VarianceRatio.kt => VarianceRatioTest.kt} (90%) diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatio.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt similarity index 90% rename from kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatio.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt index 2dfcd6b00..77163f638 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatio.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt @@ -5,7 +5,6 @@ package space.kscience.kmath.series -import space.kscience.kmath.distributions.NormalDistribution import space.kscience.kmath.operations.DoubleBufferOps.Companion.map import space.kscience.kmath.operations.DoubleField.pow import space.kscience.kmath.operations.algebra @@ -18,6 +17,12 @@ public data class VarianceRatioTestResult(val varianceRatio: Double, val zScore: public fun varianceRatioTest(series: Series, shift: Int, homoscedastic: Boolean): VarianceRatioTestResult { + /** + * Calculate the Z statistic and the p-value for the Lo and MacKinlay's Variance Ratio test (1987) + * under Homoscedastic or Heteroscedstic assumptions + * https://ssrn.com/abstract=346975 + * **/ + val sum = { x: Double, y: Double -> x + y } val mean = series.fold(0.0, sum) / series.size -- 2.34.1 From a91b43a52db60388a4947c1a277e6b26bd3e6997 Mon Sep 17 00:00:00 2001 From: mrFendel Date: Thu, 13 Apr 2023 17:52:14 +0300 Subject: [PATCH 260/275] tests for varianceRatio --- .../kmath/series/VarianceRatioTest.kt | 4 +- .../kmath/series/TestVarianceRatioTest.kt | 51 +++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 kmath-stat/src/commonTest/kotlin/space/kscience/kmath/series/TestVarianceRatioTest.kt diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt index 77163f638..b769d78a3 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt @@ -24,10 +24,10 @@ public fun varianceRatioTest(series: Series, shift: Int, homoscedastic: * **/ val sum = { x: Double, y: Double -> x + y } - + //TODO: catch if shift is too large val mean = series.fold(0.0, sum) / series.size val demeanedSquares = series.map { power(it - mean, 2) } - val variance = demeanedSquares.fold(0.0, sum) + val variance = demeanedSquares.fold(0.0, sum) // TODO: catch if variance is zero with(Double.algebra.bufferAlgebra.seriesAlgebra()) { for (i in -1..-shift + 1) { series.shiftOp(i) { v1, v2 -> v1 + v2 } } diff --git a/kmath-stat/src/commonTest/kotlin/space/kscience/kmath/series/TestVarianceRatioTest.kt b/kmath-stat/src/commonTest/kotlin/space/kscience/kmath/series/TestVarianceRatioTest.kt new file mode 100644 index 000000000..7c31663bc --- /dev/null +++ b/kmath-stat/src/commonTest/kotlin/space/kscience/kmath/series/TestVarianceRatioTest.kt @@ -0,0 +1,51 @@ +/* + * 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.algebra +import space.kscience.kmath.operations.bufferAlgebra +import kotlin.math.PI +import kotlin.test.Test +import kotlin.test.assertEquals + +class TestVarianceRatioTest { + + @Test + fun volatileData() { + with(Double.algebra.bufferAlgebra.seriesAlgebra()) { + val volatileData = series(10) { sin(PI * it + PI/2) + 1.0} + val resultHomo = varianceRatioTest(volatileData, 2, homoscedastic = true) + assertEquals(0.0, resultHomo.varianceRatio, 1e-6) + // homoscedastic zScore + assertEquals(-3.162277, resultHomo.zScore, 1e-6) + val resultHetero = varianceRatioTest(volatileData, 2, homoscedastic = false) + // heteroscedastic zScore + assertEquals(-3.535533, resultHetero.zScore, 1e-6) + } + } + + @Test + fun negativeData() { + with(Double.algebra.bufferAlgebra.seriesAlgebra()) { + val volatileData = series(10) { sin(PI * it)} + val resultHomo = varianceRatioTest(volatileData, 2, homoscedastic = true) + assertEquals(1.142857, resultHomo.varianceRatio, 1e-6) + // homoscedastic zScore + assertEquals(0.451753, resultHomo.zScore, 1e-6) + val resultHetero = varianceRatioTest(volatileData, 2, homoscedastic = false) + // heteroscedastic zScore + assertEquals(2.462591, resultHetero.zScore, 1e-6) + } + } + +// @Test +// fun zeroVolatility() { +// with(Double.algebra.bufferAlgebra.seriesAlgebra()) { +// val volatileData = series(10) { 1.0 } +// val result = varianceRatioTest(volatileData, 2, homoscedastic = true) +// } +// } +} \ No newline at end of file -- 2.34.1 From 5b95923bb9072c3437e8a3f0b65449aa90b896ef Mon Sep 17 00:00:00 2001 From: mrFendel Date: Fri, 14 Apr 2023 06:36:20 +0300 Subject: [PATCH 261/275] fixed zip in SereiesAlgebra + tests for VarianceRatio --- .../kscience/kmath/series/SeriesAlgebra.kt | 2 +- .../kmath/series/VarianceRatioTest.kt | 22 ++++++---- .../kmath/series/TestVarianceRatioTest.kt | 40 +++++++++++++------ 3 files changed, 43 insertions(+), 21 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 4b7f8b83a..9efbd629c 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 @@ -191,7 +191,7 @@ public open class SeriesAlgebra, out BA : BufferAlgebra crossinline operation: A.(left: T, right: T) -> T, ): Series { val newRange = offsetIndices.intersect(other.offsetIndices) - return seriesByOffset(startOffset = newRange.first, size = newRange.last - newRange.first) { offset -> + return seriesByOffset(startOffset = newRange.first, size = newRange.last + 1 - newRange.first) { offset -> elementAlgebra.operation( getByOffset(offset), other.getByOffset(offset) diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt index b769d78a3..9a00b1be2 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt @@ -25,17 +25,22 @@ public fun varianceRatioTest(series: Series, shift: Int, homoscedastic: val sum = { x: Double, y: Double -> x + y } //TODO: catch if shift is too large - val mean = series.fold(0.0, sum) / series.size - val demeanedSquares = series.map { power(it - mean, 2) } - val variance = demeanedSquares.fold(0.0, sum) // TODO: catch if variance is zero - with(Double.algebra.bufferAlgebra.seriesAlgebra()) { - for (i in -1..-shift + 1) { series.shiftOp(i) { v1, v2 -> v1 + v2 } } - val demeanedSquaresAgg = series.map { power(it - shift * mean, 2) } + val mean = series.fold(0.0, sum) / series.size + val demeanedSquares = series.map { power(it - mean, 2) } + val variance = demeanedSquares.fold(0.0, sum) // TODO: catch if variance is zero + + + var seriesAgg = series + for (i in 1.. v1 + v2 } + } + + val demeanedSquaresAgg = seriesAgg.map { power(it - shift * mean, 2) } val varianceAgg = demeanedSquaresAgg.fold(0.0, sum) val varianceRatio = - varianceAgg * (series.size - 1) / variance / (series.size - shift + 1) / (1 - shift / series.size) + varianceAgg * (series.size.toDouble() - 1) / variance / (series.size.toDouble() - shift.toDouble() + 1) / (1 - shift.toDouble()/series.size.toDouble()) / shift.toDouble() // calculating asymptotic variance @@ -44,8 +49,9 @@ public fun varianceRatioTest(series: Series, shift: Int, homoscedastic: phi = 2 * (2 * shift - 1.0) * (shift - 1.0) / (3 * shift * series.size) } else { // under homoscedastic null hypothesis phi = 0.0 + var shiftedProd = demeanedSquares for (j in 1.. v1 * v2 } + shiftedProd = shiftedProd.zip(demeanedSquares.moveTo(j)) { v1, v2 -> v1 * v2 } val delta = series.size * shiftedProd.fold(0.0, sum) / variance.pow(2) phi += delta * 4 * (shift - j) * (shift - j) / shift / shift // TODO: refactor with square } diff --git a/kmath-stat/src/commonTest/kotlin/space/kscience/kmath/series/TestVarianceRatioTest.kt b/kmath-stat/src/commonTest/kotlin/space/kscience/kmath/series/TestVarianceRatioTest.kt index 7c31663bc..8dcdb3a14 100644 --- a/kmath-stat/src/commonTest/kotlin/space/kscience/kmath/series/TestVarianceRatioTest.kt +++ b/kmath-stat/src/commonTest/kotlin/space/kscience/kmath/series/TestVarianceRatioTest.kt @@ -13,6 +13,21 @@ import kotlin.test.assertEquals class TestVarianceRatioTest { + // TODO: refactor Heteroscedastic zScore + @Test + fun monotonicData() { + with(Double.algebra.bufferAlgebra.seriesAlgebra()) { + val monotonicData = series(10) { it * 1.0 } + val resultHomo = varianceRatioTest(monotonicData, 2, homoscedastic = true) + assertEquals(1.818181, resultHomo.varianceRatio, 1e-6) + // homoscedastic zScore + assertEquals(2.587318, resultHomo.zScore, 1e-6) +// val resultHetero = varianceRatioTest(monotonicData, 2, homoscedastic = false) +// // heteroscedastic zScore +// assertEquals(3.253248, resultHetero.zScore, 1e-6) + } + } + @Test fun volatileData() { with(Double.algebra.bufferAlgebra.seriesAlgebra()) { @@ -21,31 +36,32 @@ class TestVarianceRatioTest { assertEquals(0.0, resultHomo.varianceRatio, 1e-6) // homoscedastic zScore assertEquals(-3.162277, resultHomo.zScore, 1e-6) - val resultHetero = varianceRatioTest(volatileData, 2, homoscedastic = false) - // heteroscedastic zScore - assertEquals(-3.535533, resultHetero.zScore, 1e-6) +// val resultHetero = varianceRatioTest(volatileData, 2, homoscedastic = false) +// // heteroscedastic zScore +// assertEquals(-3.535533, resultHetero.zScore, 1e-6) } } @Test fun negativeData() { with(Double.algebra.bufferAlgebra.seriesAlgebra()) { - val volatileData = series(10) { sin(PI * it)} - val resultHomo = varianceRatioTest(volatileData, 2, homoscedastic = true) - assertEquals(1.142857, resultHomo.varianceRatio, 1e-6) + val negativeData = series(10) { sin(it * 1.2)} + val resultHomo = varianceRatioTest(negativeData, 3, homoscedastic = true) + assertEquals(1.240031, resultHomo.varianceRatio, 1e-6) // homoscedastic zScore - assertEquals(0.451753, resultHomo.zScore, 1e-6) - val resultHetero = varianceRatioTest(volatileData, 2, homoscedastic = false) - // heteroscedastic zScore - assertEquals(2.462591, resultHetero.zScore, 1e-6) + assertEquals(0.509183, resultHomo.zScore, 1e-6) +// val resultHetero = varianceRatioTest(negativeData, 3, homoscedastic = false) +// // heteroscedastic zScore +// assertEquals(0.661798, resultHetero.zScore, 1e-6) } } + //TODO: add zero volatility Test, logReturns test, big shift Test // @Test // fun zeroVolatility() { // with(Double.algebra.bufferAlgebra.seriesAlgebra()) { -// val volatileData = series(10) { 1.0 } -// val result = varianceRatioTest(volatileData, 2, homoscedastic = true) +// val zeroVolData = series(10) { 1.0 } +// val result = varianceRatioTest(zeroVolData, 2, homoscedastic = true) // } // } } \ No newline at end of file -- 2.34.1 From 85395ff82ed76f480a67b36827397ecdd66c4728 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Fri, 14 Apr 2023 21:17:44 +0300 Subject: [PATCH 262/275] Add autodiff example --- .../kscience/kmath/expressions/autodiff.kt | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 examples/src/main/kotlin/space/kscience/kmath/expressions/autodiff.kt diff --git a/examples/src/main/kotlin/space/kscience/kmath/expressions/autodiff.kt b/examples/src/main/kotlin/space/kscience/kmath/expressions/autodiff.kt new file mode 100644 index 000000000..b1e14591a --- /dev/null +++ b/examples/src/main/kotlin/space/kscience/kmath/expressions/autodiff.kt @@ -0,0 +1,91 @@ +/* + * 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 + +import space.kscience.kmath.UnstableKMathAPI +// Only kmath-core is needed. + +// Let's declare some variables +val x by symbol +val y by symbol +val z by symbol + +@OptIn(UnstableKMathAPI::class) +fun main() { + // Let's define some random expression. + val someExpression = Double.autodiff.differentiate { + // We bind variables `x` and `y` to the builder scope, + val x = bindSymbol(x) + val y = bindSymbol(y) + + // Then we use the bindings to define expression `xy + x + y - 1` + x * y + x + y - 1 + } + + // Then we can evaluate it at any point ((-1, -1) in the case): + println(someExpression(mapOf(x to -1.0, y to -1.0))) + // >>> -2.0 + + // We can also construct its partial derivatives: + val dxExpression = someExpression.derivative(x) // ∂/∂x. Must be `y+1` + val dyExpression = someExpression.derivative(y) // ∂/∂y. Must be `x+1` + val dxdxExpression = someExpression.derivative(x, x) // ∂^2/∂x^2. Must be `0` + + // We can evaluate them as well + println(dxExpression(mapOf(x to 57.0, y to 6.0))) + // >>> 7.0 + println(dyExpression(mapOf(x to -1.0, y to 179.0))) + // >>> 0.0 + println(dxdxExpression(mapOf(x to 239.0, y to 30.0))) + // >>> 0.0 + + // You can also provide extra arguments that obviously won't affect the result: + println(dxExpression(mapOf(x to 57.0, y to 6.0, z to 42.0))) + // >>> 7.0 + println(dyExpression(mapOf(x to -1.0, y to 179.0, z to 0.0))) + // >>> 0.0 + println(dxdxExpression(mapOf(x to 239.0, y to 30.0, z to 100_000.0))) + // >>> 0.0 + + // But in case you forgot to specify bound symbol's value, exception is thrown: + println( runCatching { someExpression(mapOf(z to 4.0)) } ) + // >>> Failure(java.lang.IllegalStateException: Symbol 'x' is not supported in ...) + + // The reason is that the expression is evaluated lazily, + // and each `bindSymbol` operation actually substitutes the provided symbol with the corresponding value. + + // For example, let there be an expression + val simpleExpression = Double.autodiff.differentiate { + val x = bindSymbol(x) + x pow 2 + } + // When you evaluate it via + simpleExpression(mapOf(x to 1.0, y to 57.0, z to 179.0)) + // lambda above has the context of map `{x: 1.0, y: 57.0, z: 179.0}`. + // When x is bound, you can think of it as substitution `x -> 1.0`. + // Other values are unused which does not make any problem to us. + // But in the case the corresponding value is not provided, + // we cannot bind the variable. Thus, exception is thrown. + + // There is also a function `bindSymbolOrNull` that fixes the problem: + val fixedExpression = Double.autodiff.differentiate { + val x = bindSymbolOrNull(x) ?: const(8.0) + x pow -2 + } + println(fixedExpression()) + // >>> 0.015625 + // It works! + + // The expression provides a bunch of operations: + // 1. Constant bindings (via `const` and `number`). + // 2. Variable bindings (via `bindVariable`, `bindVariableOrNull`). + // 3. Arithmetic operations (via `+`, `-`, `*`, and `-`). + // 4. Exponentiation (via `pow` or `power`). + // 5. `exp` and `ln`. + // 6. Trigonometrical functions (`sin`, `cos`, `tan`, `cot`). + // 7. Inverse trigonometrical functions (`asin`, `acos`, `atan`, `acot`). + // 8. Hyperbolic functions and inverse hyperbolic functions. +} -- 2.34.1 From e6da61c52a7c7b38cabe5621014993eef5bdf2d2 Mon Sep 17 00:00:00 2001 From: mrFendel Date: Tue, 18 Apr 2023 01:53:07 +0300 Subject: [PATCH 263/275] refactoring --- .../kscience/kmath/series/SeriesAlgebra.kt | 6 +++--- .../kscience/kmath/series/VarianceRatioTest.kt | 18 +++++++++++------- 2 files changed, 14 insertions(+), 10 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 9efbd629c..72b9ca7a2 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 @@ -202,11 +202,11 @@ public open class SeriesAlgebra, out BA : BufferAlgebra /** * Zip buffer with itself, but shifted * */ - public inline fun Buffer.shiftOp( + public inline fun Buffer.zipWithShift( shift: Int = 1, crossinline operation: A.(left: T, right: T) -> T ): Buffer { - val shifted = this.moveTo(this.startOffset+shift) + val shifted = this.moveBy(shift) return zip(shifted, operation) } @@ -216,7 +216,7 @@ public open class SeriesAlgebra, out BA : BufferAlgebra override fun multiply(left: Buffer, right: Buffer): Buffer = left.zip(right) { l, r -> l * r } - public inline fun Buffer.diff(): Buffer = this.shiftOp {l, r -> r - l} + public fun Buffer.diff(shift: Int=1): Buffer = this.zipWithShift(shift) {l, r -> r - l} public companion object } diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt index 9a00b1be2..45bc836fe 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt @@ -12,10 +12,14 @@ import space.kscience.kmath.operations.bufferAlgebra import space.kscience.kmath.operations.fold -// TODO: add p-value +// TODO: add p-value with formula: 2*(1 - cdf(|zScore|)) public data class VarianceRatioTestResult(val varianceRatio: Double, val zScore: Double) + /** + * Container class for Variance Ratio Test result: + * ratio itself, corresponding Z-score, also it's p-value + * **/ -public fun varianceRatioTest(series: Series, shift: Int, homoscedastic: Boolean): VarianceRatioTestResult { +public fun varianceRatioTest(series: Series, shift: Int, homoscedastic: Boolean=true): VarianceRatioTestResult { /** * Calculate the Z statistic and the p-value for the Lo and MacKinlay's Variance Ratio test (1987) @@ -44,17 +48,17 @@ public fun varianceRatioTest(series: Series, shift: Int, homoscedastic: // calculating asymptotic variance - var phi: Double - if (homoscedastic) { // under homoscedastic null hypothesis - phi = 2 * (2 * shift - 1.0) * (shift - 1.0) / (3 * shift * series.size) + val phi = if (homoscedastic) { // under homoscedastic null hypothesis + 2 * (2 * shift - 1.0) * (shift - 1.0) / (3 * shift * series.size) } else { // under homoscedastic null hypothesis - phi = 0.0 + var accumulator = 0.0 var shiftedProd = demeanedSquares for (j in 1.. v1 * v2 } val delta = series.size * shiftedProd.fold(0.0, sum) / variance.pow(2) - phi += delta * 4 * (shift - j) * (shift - j) / shift / shift // TODO: refactor with square + accumulator += delta * 4 * (shift - j) * (shift - j) / shift / shift // TODO: refactor with square } + accumulator } val zScore = (varianceRatio - 1) / phi.pow(0.5) -- 2.34.1 From 98781c83adcbb62ea0a83f5c905b6bf6a85ea59c Mon Sep 17 00:00:00 2001 From: mrFendel Date: Tue, 18 Apr 2023 19:16:10 +0300 Subject: [PATCH 264/275] fixed bug with heteroscedastic z-score in Variance Ratio Test --- .../kmath/series/VarianceRatioTest.kt | 13 ++++++------- .../kmath/series/TestVarianceRatioTest.kt | 19 +++++++++---------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt index 45bc836fe..8afc01c81 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt @@ -5,11 +5,11 @@ package space.kscience.kmath.series -import space.kscience.kmath.operations.DoubleBufferOps.Companion.map import space.kscience.kmath.operations.DoubleField.pow import space.kscience.kmath.operations.algebra import space.kscience.kmath.operations.bufferAlgebra import space.kscience.kmath.operations.fold +import space.kscience.kmath.structures.slice // TODO: add p-value with formula: 2*(1 - cdf(|zScore|)) @@ -22,7 +22,7 @@ public data class VarianceRatioTestResult(val varianceRatio: Double, val zScore: public fun varianceRatioTest(series: Series, shift: Int, homoscedastic: Boolean=true): VarianceRatioTestResult { /** - * Calculate the Z statistic and the p-value for the Lo and MacKinlay's Variance Ratio test (1987) + * Calculates the Z-statistic and the p-value for the Lo and MacKinlay's Variance Ratio test (1987) * under Homoscedastic or Heteroscedstic assumptions * https://ssrn.com/abstract=346975 * **/ @@ -50,13 +50,12 @@ public fun varianceRatioTest(series: Series, shift: Int, homoscedastic: // calculating asymptotic variance val phi = if (homoscedastic) { // under homoscedastic null hypothesis 2 * (2 * shift - 1.0) * (shift - 1.0) / (3 * shift * series.size) - } else { // under homoscedastic null hypothesis + } else { // under heteroscedastic null hypothesis var accumulator = 0.0 - var shiftedProd = demeanedSquares for (j in 1.. v1 * v2 } - val delta = series.size * shiftedProd.fold(0.0, sum) / variance.pow(2) - accumulator += delta * 4 * (shift - j) * (shift - j) / shift / shift // TODO: refactor with square + var temp = demeanedSquares + val delta = series.size * temp.zipWithShift(j) { v1, v2 -> v1 * v2 }.fold(0.0, sum) / variance.pow(2) + accumulator += delta * 4 * (shift - j).toDouble().pow(2) / shift.toDouble().pow(2) } accumulator } diff --git a/kmath-stat/src/commonTest/kotlin/space/kscience/kmath/series/TestVarianceRatioTest.kt b/kmath-stat/src/commonTest/kotlin/space/kscience/kmath/series/TestVarianceRatioTest.kt index 8dcdb3a14..0ece143eb 100644 --- a/kmath-stat/src/commonTest/kotlin/space/kscience/kmath/series/TestVarianceRatioTest.kt +++ b/kmath-stat/src/commonTest/kotlin/space/kscience/kmath/series/TestVarianceRatioTest.kt @@ -13,7 +13,6 @@ import kotlin.test.assertEquals class TestVarianceRatioTest { - // TODO: refactor Heteroscedastic zScore @Test fun monotonicData() { with(Double.algebra.bufferAlgebra.seriesAlgebra()) { @@ -22,9 +21,9 @@ class TestVarianceRatioTest { assertEquals(1.818181, resultHomo.varianceRatio, 1e-6) // homoscedastic zScore assertEquals(2.587318, resultHomo.zScore, 1e-6) -// val resultHetero = varianceRatioTest(monotonicData, 2, homoscedastic = false) -// // heteroscedastic zScore -// assertEquals(3.253248, resultHetero.zScore, 1e-6) + val resultHetero = varianceRatioTest(monotonicData, 2, homoscedastic = false) + // heteroscedastic zScore + assertEquals(0.819424, resultHetero.zScore, 1e-6) } } @@ -36,9 +35,9 @@ class TestVarianceRatioTest { assertEquals(0.0, resultHomo.varianceRatio, 1e-6) // homoscedastic zScore assertEquals(-3.162277, resultHomo.zScore, 1e-6) -// val resultHetero = varianceRatioTest(volatileData, 2, homoscedastic = false) -// // heteroscedastic zScore -// assertEquals(-3.535533, resultHetero.zScore, 1e-6) + val resultHetero = varianceRatioTest(volatileData, 2, homoscedastic = false) + // heteroscedastic zScore + assertEquals(-1.0540925, resultHetero.zScore, 1e-6) } } @@ -50,9 +49,9 @@ class TestVarianceRatioTest { assertEquals(1.240031, resultHomo.varianceRatio, 1e-6) // homoscedastic zScore assertEquals(0.509183, resultHomo.zScore, 1e-6) -// val resultHetero = varianceRatioTest(negativeData, 3, homoscedastic = false) -// // heteroscedastic zScore -// assertEquals(0.661798, resultHetero.zScore, 1e-6) + val resultHetero = varianceRatioTest(negativeData, 3, homoscedastic = false) + // heteroscedastic zScore + assertEquals(0.209202, resultHetero.zScore, 1e-6) } } -- 2.34.1 From 0193349f9413a79fb1b06e05a437b8e609e0a6c3 Mon Sep 17 00:00:00 2001 From: mrFendel Date: Wed, 19 Apr 2023 01:36:54 +0300 Subject: [PATCH 265/275] requirements, default parameters, new Test for varianceRatioTest --- .../space/kscience/kmath/ejml/_generated.kt | 2 +- .../kmath/series/VarianceRatioTest.kt | 12 ++++++----- .../kmath/series/TestVarianceRatioTest.kt | 21 ++++++++++--------- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt index c56583fa8..8ad7f7293 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt @@ -19,9 +19,9 @@ import org.ejml.sparse.csc.factory.DecompositionFactory_DSCC import org.ejml.sparse.csc.factory.DecompositionFactory_FSCC import org.ejml.sparse.csc.factory.LinearSolverFactory_DSCC import org.ejml.sparse.csc.factory.LinearSolverFactory_FSCC -import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.linear.* import space.kscience.kmath.linear.Matrix +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.nd.StructureFeature import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.FloatField diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt index 8afc01c81..d81a6c317 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt @@ -9,11 +9,10 @@ import space.kscience.kmath.operations.DoubleField.pow import space.kscience.kmath.operations.algebra import space.kscience.kmath.operations.bufferAlgebra import space.kscience.kmath.operations.fold -import space.kscience.kmath.structures.slice // TODO: add p-value with formula: 2*(1 - cdf(|zScore|)) -public data class VarianceRatioTestResult(val varianceRatio: Double, val zScore: Double) +public data class VarianceRatioTestResult(val varianceRatio: Double=1.0, val zScore: Double=0.0) /** * Container class for Variance Ratio Test result: * ratio itself, corresponding Z-score, also it's p-value @@ -27,12 +26,15 @@ public fun varianceRatioTest(series: Series, shift: Int, homoscedastic: * https://ssrn.com/abstract=346975 * **/ + require(shift > 1) {"Shift must be greater than one"} + require(shift < series.size) {"Shift must be smaller than sample size"} val sum = { x: Double, y: Double -> x + y } - //TODO: catch if shift is too large + with(Double.algebra.bufferAlgebra.seriesAlgebra()) { val mean = series.fold(0.0, sum) / series.size val demeanedSquares = series.map { power(it - mean, 2) } - val variance = demeanedSquares.fold(0.0, sum) // TODO: catch if variance is zero + val variance = demeanedSquares.fold(0.0, sum) + if (variance == 0.0) return VarianceRatioTestResult() var seriesAgg = series @@ -53,7 +55,7 @@ public fun varianceRatioTest(series: Series, shift: Int, homoscedastic: } else { // under heteroscedastic null hypothesis var accumulator = 0.0 for (j in 1.. v1 * v2 }.fold(0.0, sum) / variance.pow(2) accumulator += delta * 4 * (shift - j).toDouble().pow(2) / shift.toDouble().pow(2) } diff --git a/kmath-stat/src/commonTest/kotlin/space/kscience/kmath/series/TestVarianceRatioTest.kt b/kmath-stat/src/commonTest/kotlin/space/kscience/kmath/series/TestVarianceRatioTest.kt index 0ece143eb..8e559276c 100644 --- a/kmath-stat/src/commonTest/kotlin/space/kscience/kmath/series/TestVarianceRatioTest.kt +++ b/kmath-stat/src/commonTest/kotlin/space/kscience/kmath/series/TestVarianceRatioTest.kt @@ -31,7 +31,7 @@ class TestVarianceRatioTest { fun volatileData() { with(Double.algebra.bufferAlgebra.seriesAlgebra()) { val volatileData = series(10) { sin(PI * it + PI/2) + 1.0} - val resultHomo = varianceRatioTest(volatileData, 2, homoscedastic = true) + val resultHomo = varianceRatioTest(volatileData, 2) assertEquals(0.0, resultHomo.varianceRatio, 1e-6) // homoscedastic zScore assertEquals(-3.162277, resultHomo.zScore, 1e-6) @@ -45,7 +45,7 @@ class TestVarianceRatioTest { fun negativeData() { with(Double.algebra.bufferAlgebra.seriesAlgebra()) { val negativeData = series(10) { sin(it * 1.2)} - val resultHomo = varianceRatioTest(negativeData, 3, homoscedastic = true) + val resultHomo = varianceRatioTest(negativeData, 3) assertEquals(1.240031, resultHomo.varianceRatio, 1e-6) // homoscedastic zScore assertEquals(0.509183, resultHomo.zScore, 1e-6) @@ -55,12 +55,13 @@ class TestVarianceRatioTest { } } - //TODO: add zero volatility Test, logReturns test, big shift Test -// @Test -// fun zeroVolatility() { -// with(Double.algebra.bufferAlgebra.seriesAlgebra()) { -// val zeroVolData = series(10) { 1.0 } -// val result = varianceRatioTest(zeroVolData, 2, homoscedastic = true) -// } -// } + @Test + fun zeroVolatility() { + with(Double.algebra.bufferAlgebra.seriesAlgebra()) { + val zeroVolData = series(10) { 0.0 } + val result = varianceRatioTest(zeroVolData, 4) + assertEquals(1.0, result.varianceRatio, 1e-6) + assertEquals(0.0, result.zScore, 1e-6) + } + } } \ No newline at end of file -- 2.34.1 From 1e27af9cf577478a2b6b582e9882022f91e36610 Mon Sep 17 00:00:00 2001 From: mrFendel Date: Wed, 19 Apr 2023 17:13:47 +0300 Subject: [PATCH 266/275] - Zelen-Severo CDF aproximation - p-value for varianceRatioTest --- .../kmath/series/VarianceRatioTest.kt | 11 +++++++-- .../kscience/kmath/series/zSNormalCdf.kt | 24 +++++++++++++++++++ .../kmath/series/TestVarianceRatioTest.kt | 5 ++++ 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/zSNormalCdf.kt diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt index d81a6c317..280a9db64 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt @@ -9,10 +9,11 @@ import space.kscience.kmath.operations.DoubleField.pow import space.kscience.kmath.operations.algebra import space.kscience.kmath.operations.bufferAlgebra import space.kscience.kmath.operations.fold +import kotlin.math.absoluteValue // TODO: add p-value with formula: 2*(1 - cdf(|zScore|)) -public data class VarianceRatioTestResult(val varianceRatio: Double=1.0, val zScore: Double=0.0) +public data class VarianceRatioTestResult(val varianceRatio: Double=1.0, val zScore: Double=0.0, val pValue: Double=0.5) /** * Container class for Variance Ratio Test result: * ratio itself, corresponding Z-score, also it's p-value @@ -23,6 +24,7 @@ public fun varianceRatioTest(series: Series, shift: Int, homoscedastic: /** * Calculates the Z-statistic and the p-value for the Lo and MacKinlay's Variance Ratio test (1987) * under Homoscedastic or Heteroscedstic assumptions + * with two-sided p-value test * https://ssrn.com/abstract=346975 * **/ @@ -63,6 +65,11 @@ public fun varianceRatioTest(series: Series, shift: Int, homoscedastic: } val zScore = (varianceRatio - 1) / phi.pow(0.5) - return VarianceRatioTestResult(varianceRatio, zScore) + val pValue = 2*(1 - zSNormalCDF(zScore.absoluteValue)) + return VarianceRatioTestResult(varianceRatio, zScore, pValue) } } + + + + diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/zSNormalCdf.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/zSNormalCdf.kt new file mode 100644 index 000000000..1eb733ea9 --- /dev/null +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/zSNormalCdf.kt @@ -0,0 +1,24 @@ +/* + * 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.DoubleField.pow +import kotlin.math.PI +import kotlin.math.absoluteValue +import kotlin.math.exp + +public fun zSNormalCDF(x: Double): Double { + + /** + * Zelen & Severo approximation for the standard normal CDF. + * The error is bounded by 7.5 * 10e-8. + * */ + + val t = 1 / (1 + 0.2316419 * x.absoluteValue) + val summ = 0.319381530*t - 0.356563782*t.pow(2) + 1.781477937*t.pow(3) - 1.821255978*t.pow(4) + 1.330274429*t.pow(5) + val temp = summ * exp(-x.absoluteValue.pow(2) / 2) / (2 * PI).pow(0.5) + return if (x >= 0) 1 - temp else temp +} \ No newline at end of file diff --git a/kmath-stat/src/commonTest/kotlin/space/kscience/kmath/series/TestVarianceRatioTest.kt b/kmath-stat/src/commonTest/kotlin/space/kscience/kmath/series/TestVarianceRatioTest.kt index 8e559276c..afc0d541d 100644 --- a/kmath-stat/src/commonTest/kotlin/space/kscience/kmath/series/TestVarianceRatioTest.kt +++ b/kmath-stat/src/commonTest/kotlin/space/kscience/kmath/series/TestVarianceRatioTest.kt @@ -21,9 +21,11 @@ class TestVarianceRatioTest { assertEquals(1.818181, resultHomo.varianceRatio, 1e-6) // homoscedastic zScore assertEquals(2.587318, resultHomo.zScore, 1e-6) + assertEquals(.0096, resultHomo.pValue, 1e-4) val resultHetero = varianceRatioTest(monotonicData, 2, homoscedastic = false) // heteroscedastic zScore assertEquals(0.819424, resultHetero.zScore, 1e-6) + assertEquals(.4125, resultHetero.pValue, 1e-4) } } @@ -35,9 +37,11 @@ class TestVarianceRatioTest { assertEquals(0.0, resultHomo.varianceRatio, 1e-6) // homoscedastic zScore assertEquals(-3.162277, resultHomo.zScore, 1e-6) + assertEquals(.0015, resultHomo.pValue, 1e-4) val resultHetero = varianceRatioTest(volatileData, 2, homoscedastic = false) // heteroscedastic zScore assertEquals(-1.0540925, resultHetero.zScore, 1e-6) + assertEquals(.2918, resultHetero.pValue, 1e-4) } } @@ -62,6 +66,7 @@ class TestVarianceRatioTest { val result = varianceRatioTest(zeroVolData, 4) assertEquals(1.0, result.varianceRatio, 1e-6) assertEquals(0.0, result.zScore, 1e-6) + assertEquals(0.5, result.pValue, 1e-4) } } } \ No newline at end of file -- 2.34.1 From 0c565c6056b5c2a8d1eb0aacb3ac49929232dc52 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 May 2023 13:50:29 +0000 Subject: [PATCH 267/275] Bump gradle/gradle-build-action in /.github/workflows Bumps [gradle/gradle-build-action](https://github.com/gradle/gradle-build-action) from 2.1.5 to 2.4.2. - [Release notes](https://github.com/gradle/gradle-build-action/releases) - [Commits](https://github.com/gradle/gradle-build-action/compare/v2.1.5...v2.4.2) --- updated-dependencies: - dependency-name: gradle/gradle-build-action dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 2 +- .github/workflows/pages.yml | 2 +- .github/workflows/publish.yml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 20d5f9a68..6ad294e18 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,6 +19,6 @@ jobs: - name: Gradle Wrapper Validation uses: gradle/wrapper-validation-action@v1.0.4 - name: Gradle Build - uses: gradle/gradle-build-action@v2.3.2 + uses: gradle/gradle-build-action@v2.4.2 with: arguments: test jvmTest diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 2abaf0b9f..ba1f5d1e3 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -22,7 +22,7 @@ jobs: key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }} restore-keys: | ${{ runner.os }}-gradle- - - uses: gradle/gradle-build-action@v2.1.5 + - uses: gradle/gradle-build-action@v2.4.2 with: arguments: dokkaHtmlMultiModule --no-parallel - uses: JamesIves/github-pages-deploy-action@v4.3.0 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index ab9243f15..31d539cdd 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -28,7 +28,7 @@ jobs: ${{ runner.os }}-gradle- - name: Publish Windows Artifacts if: matrix.os == 'windows-latest' - uses: gradle/gradle-build-action@v2.4.0 + uses: gradle/gradle-build-action@v2.4.2 with: arguments: | publishAllPublicationsToSpaceRepository @@ -37,7 +37,7 @@ jobs: -Ppublishing.space.token=${{ secrets.SPACE_APP_SECRET }} - name: Publish Mac Artifacts if: matrix.os == 'macOS-latest' - uses: gradle/gradle-build-action@v2.4.0 + uses: gradle/gradle-build-action@v2.4.2 with: arguments: | publishMacosX64PublicationToSpaceRepository -- 2.34.1 From 16385b5f4e8e15fcb27774ff41b5443be0cd9642 Mon Sep 17 00:00:00 2001 From: mrFendel Date: Fri, 5 May 2023 18:45:54 +0300 Subject: [PATCH 268/275] -- refactoring --- .../{series => distributions}/zSNormalCdf.kt | 12 +-- .../kscience/kmath/series/SeriesAlgebra.kt | 2 +- .../kmath/series/VarianceRatioTest.kt | 89 +++++++++---------- 3 files changed, 51 insertions(+), 52 deletions(-) rename kmath-stat/src/commonMain/kotlin/space/kscience/kmath/{series => distributions}/zSNormalCdf.kt (79%) diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/zSNormalCdf.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/zSNormalCdf.kt similarity index 79% rename from kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/zSNormalCdf.kt rename to kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/zSNormalCdf.kt index 1eb733ea9..adfbbc9cd 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/zSNormalCdf.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/zSNormalCdf.kt @@ -3,19 +3,19 @@ * 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 +package space.kscience.kmath.distributions import space.kscience.kmath.operations.DoubleField.pow import kotlin.math.PI import kotlin.math.absoluteValue import kotlin.math.exp -public fun zSNormalCDF(x: Double): Double { - /** - * Zelen & Severo approximation for the standard normal CDF. - * The error is bounded by 7.5 * 10e-8. - * */ +/** + * Zelen & Severo approximation for the standard normal CDF. + * The error is bounded by 7.5 * 10e-8. + * */ +public fun zSNormalCDF(x: Double): Double { val t = 1 / (1 + 0.2316419 * x.absoluteValue) val summ = 0.319381530*t - 0.356563782*t.pow(2) + 1.781477937*t.pow(3) - 1.821255978*t.pow(4) + 1.330274429*t.pow(5) 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 72b9ca7a2..cabff25e6 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 @@ -216,7 +216,7 @@ public open class SeriesAlgebra, out BA : BufferAlgebra override fun multiply(left: Buffer, right: Buffer): Buffer = left.zip(right) { l, r -> l * r } - public fun Buffer.diff(shift: Int=1): Buffer = this.zipWithShift(shift) {l, r -> r - l} + public fun Buffer.difference(shift: Int=1): Buffer = this.zipWithShift(shift) {l, r -> r - l} public companion object } diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt index 280a9db64..3c6747ed2 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.series +import space.kscience.kmath.distributions.zSNormalCDF import space.kscience.kmath.operations.DoubleField.pow import space.kscience.kmath.operations.algebra import space.kscience.kmath.operations.bufferAlgebra @@ -12,62 +13,60 @@ import space.kscience.kmath.operations.fold import kotlin.math.absoluteValue -// TODO: add p-value with formula: 2*(1 - cdf(|zScore|)) +/** + * Container class for Variance Ratio Test result: + * ratio itself, corresponding Z-score, also it's p-value + * **/ public data class VarianceRatioTestResult(val varianceRatio: Double=1.0, val zScore: Double=0.0, val pValue: Double=0.5) - /** - * Container class for Variance Ratio Test result: - * ratio itself, corresponding Z-score, also it's p-value - * **/ -public fun varianceRatioTest(series: Series, shift: Int, homoscedastic: Boolean=true): VarianceRatioTestResult { - /** - * Calculates the Z-statistic and the p-value for the Lo and MacKinlay's Variance Ratio test (1987) - * under Homoscedastic or Heteroscedstic assumptions - * with two-sided p-value test - * https://ssrn.com/abstract=346975 - * **/ +/** + * Calculates the Z-statistic and the p-value for the Lo and MacKinlay's Variance Ratio test (1987) + * under Homoscedastic or Heteroscedstic assumptions + * with two-sided p-value test + * https://ssrn.com/abstract=346975 + * **/ +public fun SeriesAlgebra.varianceRatioTest(series: Series, shift: Int, homoscedastic: Boolean=true): VarianceRatioTestResult { require(shift > 1) {"Shift must be greater than one"} require(shift < series.size) {"Shift must be smaller than sample size"} val sum = { x: Double, y: Double -> x + y } - with(Double.algebra.bufferAlgebra.seriesAlgebra()) { - val mean = series.fold(0.0, sum) / series.size - val demeanedSquares = series.map { power(it - mean, 2) } - val variance = demeanedSquares.fold(0.0, sum) - if (variance == 0.0) return VarianceRatioTestResult() + + val mean = series.fold(0.0, sum) / series.size + val demeanedSquares = series.map { (it - mean).pow(2) } + val variance = demeanedSquares.fold(0.0, sum) + if (variance == 0.0) return VarianceRatioTestResult() - var seriesAgg = series - for (i in 1.. v1 + v2 } - } - - val demeanedSquaresAgg = seriesAgg.map { power(it - shift * mean, 2) } - val varianceAgg = demeanedSquaresAgg.fold(0.0, sum) - - val varianceRatio = - varianceAgg * (series.size.toDouble() - 1) / variance / (series.size.toDouble() - shift.toDouble() + 1) / (1 - shift.toDouble()/series.size.toDouble()) / shift.toDouble() - - - // calculating asymptotic variance - val phi = if (homoscedastic) { // under homoscedastic null hypothesis - 2 * (2 * shift - 1.0) * (shift - 1.0) / (3 * shift * series.size) - } else { // under heteroscedastic null hypothesis - var accumulator = 0.0 - for (j in 1.. v1 * v2 }.fold(0.0, sum) / variance.pow(2) - accumulator += delta * 4 * (shift - j).toDouble().pow(2) / shift.toDouble().pow(2) - } - accumulator - } - - val zScore = (varianceRatio - 1) / phi.pow(0.5) - val pValue = 2*(1 - zSNormalCDF(zScore.absoluteValue)) - return VarianceRatioTestResult(varianceRatio, zScore, pValue) + var seriesAgg = series + for (i in 1.. v1 + v2 } } + + val demeanedSquaresAgg = seriesAgg.map { (it - shift * mean).pow(2) } + val varianceAgg = demeanedSquaresAgg.fold(0.0, sum) + + val varianceRatio = + varianceAgg * (series.size.toDouble() - 1) / variance / (series.size.toDouble() - shift.toDouble() + 1) / (1 - shift.toDouble()/series.size.toDouble()) / shift.toDouble() + + + // calculating asymptotic variance + val phi = if (homoscedastic) { // under homoscedastic null hypothesis + 2 * (2 * shift - 1.0) * (shift - 1.0) / (3 * shift * series.size) + } else { // under heteroscedastic null hypothesis + var accumulator = 0.0 + for (j in 1.. v1 * v2 }.fold(0.0, sum) / variance.pow(2) + accumulator += delta * 4 * (shift - j).toDouble().pow(2) / shift.toDouble().pow(2) + } + accumulator + } + + val zScore = (varianceRatio - 1) / phi.pow(0.5) + val pValue = 2*(1 - zSNormalCDF(zScore.absoluteValue)) + return VarianceRatioTestResult(varianceRatio, zScore, pValue) } -- 2.34.1 From f44039e30915530e260c1de6fb9d955c3b76d73b Mon Sep 17 00:00:00 2001 From: mrFendel Date: Fri, 5 May 2023 18:50:10 +0300 Subject: [PATCH 269/275] -- refactoring --- .../kotlin/space/kscience/kmath/series/VarianceRatioTest.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt index 3c6747ed2..6a2f5e426 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt @@ -7,8 +7,6 @@ package space.kscience.kmath.series import space.kscience.kmath.distributions.zSNormalCDF import space.kscience.kmath.operations.DoubleField.pow -import space.kscience.kmath.operations.algebra -import space.kscience.kmath.operations.bufferAlgebra import space.kscience.kmath.operations.fold import kotlin.math.absoluteValue -- 2.34.1 From 8eb25596a0c0847c5330bb5f3c780a3710052304 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 9 May 2023 19:22:39 +0300 Subject: [PATCH 270/275] Variance test post-merge cleanup --- .space.kts | 4 +-- build.gradle.kts | 2 +- .../space/kscience/kmath/ejml/_generated.kt | 2 +- .../kmath/distributions/NormalDistribution.kt | 18 +++++++++++- .../kmath/distributions/zSNormalCdf.kt | 24 ---------------- .../kmath/series/VarianceRatioTest.kt | 28 +++++++++++++------ 6 files changed, 40 insertions(+), 38 deletions(-) delete mode 100644 kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/zSNormalCdf.kt diff --git a/.space.kts b/.space.kts index c9500e967..e4d7522e3 100644 --- a/.space.kts +++ b/.space.kts @@ -1,3 +1,3 @@ -job("Build") { - gradlew("openjdk:11", "build") +job("Build and run tests") { + gradlew("amazoncorretto:17-alpine", "build") } \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index ec67eaa54..40ae9f210 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,7 +15,7 @@ allprojects { } group = "space.kscience" - version = "0.3.1-dev-RC" + version = "0.3.1" } subprojects { diff --git a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt index 8ad7f7293..c56583fa8 100644 --- a/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt +++ b/kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/_generated.kt @@ -19,9 +19,9 @@ import org.ejml.sparse.csc.factory.DecompositionFactory_DSCC import org.ejml.sparse.csc.factory.DecompositionFactory_FSCC import org.ejml.sparse.csc.factory.LinearSolverFactory_DSCC import org.ejml.sparse.csc.factory.LinearSolverFactory_FSCC +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.linear.* import space.kscience.kmath.linear.Matrix -import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.nd.StructureFeature import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.FloatField 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 ca3537005..ae814254b 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,6 +6,7 @@ package space.kscience.kmath.distributions import space.kscience.kmath.chains.Chain +import space.kscience.kmath.operations.DoubleField.pow import space.kscience.kmath.random.RandomGenerator import space.kscience.kmath.samplers.GaussianSampler import space.kscience.kmath.samplers.InternalErf @@ -34,8 +35,23 @@ public class NormalDistribution(public val sampler: GaussianSampler) : Distribut } } - private companion object { + public companion object { private val SQRT2 = sqrt(2.0) + + /** + * Zelen & Severo approximation for the standard normal CDF. + * The error upper boundary by 7.5 * 10e-8. + */ + public fun zSNormalCDF(x: Double): Double { + val t = 1 / (1 + 0.2316419 * abs(x)) + val sum = 0.319381530 * t - + 0.356563782 * t.pow(2) + + 1.781477937 * t.pow(3) - + 1.821255978 * t.pow(4) + + 1.330274429 * t.pow(5) + val temp = sum * exp(-abs(x).pow(2) / 2) / (2 * PI).pow(0.5) + return if (x >= 0) 1 - temp else temp + } } } diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/zSNormalCdf.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/zSNormalCdf.kt deleted file mode 100644 index adfbbc9cd..000000000 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/distributions/zSNormalCdf.kt +++ /dev/null @@ -1,24 +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.distributions - -import space.kscience.kmath.operations.DoubleField.pow -import kotlin.math.PI -import kotlin.math.absoluteValue -import kotlin.math.exp - - -/** - * Zelen & Severo approximation for the standard normal CDF. - * The error is bounded by 7.5 * 10e-8. - * */ -public fun zSNormalCDF(x: Double): Double { - - val t = 1 / (1 + 0.2316419 * x.absoluteValue) - val summ = 0.319381530*t - 0.356563782*t.pow(2) + 1.781477937*t.pow(3) - 1.821255978*t.pow(4) + 1.330274429*t.pow(5) - val temp = summ * exp(-x.absoluteValue.pow(2) / 2) / (2 * PI).pow(0.5) - return if (x >= 0) 1 - temp else temp -} \ No newline at end of file diff --git a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt index 6a2f5e426..4becb3413 100644 --- a/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt +++ b/kmath-stat/src/commonMain/kotlin/space/kscience/kmath/series/VarianceRatioTest.kt @@ -5,7 +5,7 @@ package space.kscience.kmath.series -import space.kscience.kmath.distributions.zSNormalCDF +import space.kscience.kmath.distributions.NormalDistribution import space.kscience.kmath.operations.DoubleField.pow import space.kscience.kmath.operations.fold import kotlin.math.absoluteValue @@ -14,8 +14,12 @@ import kotlin.math.absoluteValue /** * Container class for Variance Ratio Test result: * ratio itself, corresponding Z-score, also it's p-value - * **/ -public data class VarianceRatioTestResult(val varianceRatio: Double=1.0, val zScore: Double=0.0, val pValue: Double=0.5) + */ +public data class VarianceRatioTestResult( + val varianceRatio: Double = 1.0, + val zScore: Double = 0.0, + val pValue: Double = 0.5, +) /** @@ -23,11 +27,17 @@ public data class VarianceRatioTestResult(val varianceRatio: Double=1.0, val zSc * under Homoscedastic or Heteroscedstic assumptions * with two-sided p-value test * https://ssrn.com/abstract=346975 - * **/ -public fun SeriesAlgebra.varianceRatioTest(series: Series, shift: Int, homoscedastic: Boolean=true): VarianceRatioTestResult { + * + * @author https://github.com/mrFendel + */ +public fun SeriesAlgebra.varianceRatioTest( + series: Series, + shift: Int, + homoscedastic: Boolean = true, +): VarianceRatioTestResult { - require(shift > 1) {"Shift must be greater than one"} - require(shift < series.size) {"Shift must be smaller than sample size"} + require(shift > 1) { "Shift must be greater than one" } + require(shift < series.size) { "Shift must be smaller than sample size" } val sum = { x: Double, y: Double -> x + y } @@ -46,7 +56,7 @@ public fun SeriesAlgebra.varianceRatioTest(series: Series.varianceRatioTest(series: Series Date: Tue, 9 May 2023 19:28:38 +0300 Subject: [PATCH 271/275] update space automation --- .gitignore | 1 + .space.kts | 49 ++++++++++++++++++++++++++++++++++++++++++-- test-utils/README.md | 4 ++++ 3 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 test-utils/README.md diff --git a/.gitignore b/.gitignore index 7713a9f96..96a556ae1 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ out/ .idea/ .vscode/ +.fleet/ # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) diff --git a/.space.kts b/.space.kts index e4d7522e3..ce52a2f5c 100644 --- a/.space.kts +++ b/.space.kts @@ -1,3 +1,48 @@ -job("Build and run tests") { - gradlew("amazoncorretto:17-alpine", "build") +import kotlin.io.path.readText + +val projectName = "kmath" + +job("Build") { + //Perform only jvm tests + gradlew("spc.registry.jetbrains.space/p/sci/containers/kotlin-ci:1.0.3", "test", "jvmTest") +} + +job("Publish") { + startOn { + gitPush { enabled = false } + } + container("spc.registry.jetbrains.space/p/sci/containers/kotlin-ci:1.0.3") { + env["SPACE_USER"] = "{{ project:space_user }}" + env["SPACE_TOKEN"] = "{{ project:space_token }}" + kotlinScript { api -> + + val spaceUser = System.getenv("SPACE_USER") + val spaceToken = System.getenv("SPACE_TOKEN") + + // write the version to the build directory + api.gradlew("version") + + //read the version from build file + val version = java.nio.file.Path.of("build/project-version.txt").readText() + + val revisionSuffix = if (version.endsWith("SNAPSHOT")) { + "-" + api.gitRevision().take(7) + } else { + "" + } + + api.space().projects.automation.deployments.start( + project = api.projectIdentifier(), + targetIdentifier = TargetIdentifier.Key(projectName), + version = version+revisionSuffix, + // automatically update deployment status based on the status of a job + syncWithAutomationJob = true + ) + api.gradlew( + "publishAllPublicationsToSpaceRepository", + "-Ppublishing.space.user=\"$spaceUser\"", + "-Ppublishing.space.token=\"$spaceToken\"", + ) + } + } } \ No newline at end of file diff --git a/test-utils/README.md b/test-utils/README.md new file mode 100644 index 000000000..6ff8b98e8 --- /dev/null +++ b/test-utils/README.md @@ -0,0 +1,4 @@ +# Module test-utils + + + -- 2.34.1 From 4ab2244ac93662ac24b64b3ff860b3367a13ef60 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 9 May 2023 19:44:39 +0300 Subject: [PATCH 272/275] update space automation --- CHANGELOG.md | 2 +- .../kotlin/space/kscience/kmath/ast/utils.kt | 2 + kmath-core/api/kmath-core.api | 893 ++++++++++++++++-- .../kmath/structures/bufferPrimitiveAccess.kt | 1 - kmath-memory/api/kmath-memory.api | 19 +- kmath-viktor/api/kmath-viktor.api | 8 +- 6 files changed, 821 insertions(+), 104 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 998e6daae..2f011881f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ ### Security -## 0.3.1-dev-RC - 2023-04-09 +## 0.3.1 - 2023-04-09 ### Added - Wasm support for `memory`, `core`, `complex` and `functions` modules. diff --git a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt index 9f0fb33ab..be890273d 100644 --- a/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt +++ b/kmath-ast/src/jvmTest/kotlin/space/kscience/kmath/ast/utils.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.ast +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.Symbol @@ -30,6 +31,7 @@ private object GenericAsmCompilerTestContext : CompilerTestContext { asmCompile(algebra as Algebra, arguments) } +@OptIn(UnstableKMathAPI::class) private object PrimitiveAsmCompilerTestContext : CompilerTestContext { override fun MST.compileToExpression(algebra: IntRing): Expression = asmCompileToExpression(algebra) override fun MST.compile(algebra: IntRing, arguments: Map): Int = asmCompile(algebra, arguments) diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index 737d33f1c..e3c33e8c6 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -1,27 +1,100 @@ +public abstract interface class space/kscience/kmath/data/ColumnarData { + public abstract fun get (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/structures/Buffer; + public abstract fun getSize ()I +} + public final class space/kscience/kmath/data/ColumnarDataKt { + public static final fun asColumnarData (Lspace/kscience/kmath/nd/Structure2D;Ljava/util/Map;)Lspace/kscience/kmath/data/ColumnarData; public static final fun getIndices (Lspace/kscience/kmath/data/ColumnarData;)Lkotlin/ranges/IntRange; } +public abstract interface class space/kscience/kmath/data/XYColumnarData : space/kscience/kmath/data/ColumnarData { + public static final field Companion Lspace/kscience/kmath/data/XYColumnarData$Companion; + public fun get (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/structures/Buffer; + public abstract fun getX ()Lspace/kscience/kmath/structures/Buffer; + public abstract fun getY ()Lspace/kscience/kmath/structures/Buffer; +} + public final class space/kscience/kmath/data/XYColumnarData$Companion { + public final fun of (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/data/XYColumnarData; } public final class space/kscience/kmath/data/XYColumnarDataKt { + public static final fun asXYData (Lspace/kscience/kmath/data/ColumnarData;Lspace/kscience/kmath/expressions/Symbol;Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/data/XYColumnarData; + public static final fun asXYData (Lspace/kscience/kmath/nd/Structure2D;II)Lspace/kscience/kmath/data/XYColumnarData; public static synthetic fun asXYData$default (Lspace/kscience/kmath/nd/Structure2D;IIILjava/lang/Object;)Lspace/kscience/kmath/data/XYColumnarData; } +public abstract interface class space/kscience/kmath/data/XYErrorColumnarData : space/kscience/kmath/data/XYColumnarData { + public static final field Companion Lspace/kscience/kmath/data/XYErrorColumnarData$Companion; + public fun get (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/structures/Buffer; + public abstract fun getYErr ()Lspace/kscience/kmath/structures/Buffer; +} + public final class space/kscience/kmath/data/XYErrorColumnarData$Companion { public final fun of (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/data/XYErrorColumnarData; } +public abstract interface class space/kscience/kmath/data/XYZColumnarData : space/kscience/kmath/data/XYColumnarData { + public fun get (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/structures/Buffer; + public abstract fun getZ ()Lspace/kscience/kmath/structures/Buffer; +} + public abstract interface class space/kscience/kmath/domains/Domain { public abstract fun contains (Lspace/kscience/kmath/structures/Buffer;)Z public abstract fun getDimension ()I } +public abstract class space/kscience/kmath/domains/Domain1D : space/kscience/kmath/domains/Domain { + public fun (Lkotlin/ranges/ClosedRange;)V + public final fun contains (Ljava/lang/Comparable;)Z + public fun contains (Lspace/kscience/kmath/structures/Buffer;)Z + public fun getDimension ()I + public final fun getRange ()Lkotlin/ranges/ClosedRange; +} + public final class space/kscience/kmath/domains/Domain1DKt { public static final fun getCenter (Lspace/kscience/kmath/domains/Domain1D;)D } +public abstract interface class space/kscience/kmath/domains/DoubleDomain : space/kscience/kmath/domains/Domain { + public abstract fun getLowerBound (I)D + public abstract fun getUpperBound (I)D + public abstract fun volume ()D +} + +public final class space/kscience/kmath/domains/DoubleDomain1D : space/kscience/kmath/domains/Domain1D, space/kscience/kmath/domains/DoubleDomain { + public fun (Lkotlin/ranges/ClosedFloatingPointRange;)V + public fun equals (Ljava/lang/Object;)Z + public final fun getDoubleRange ()Lkotlin/ranges/ClosedFloatingPointRange; + public fun getLowerBound (I)D + public fun getUpperBound (I)D + public fun hashCode ()I + public fun toString ()Ljava/lang/String; + public fun volume ()D +} + +public final class space/kscience/kmath/domains/HyperSquareDomain : space/kscience/kmath/domains/DoubleDomain { + public fun (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)V + public fun contains (Lspace/kscience/kmath/structures/Buffer;)Z + public final fun getCenter-Dv3HvWU ()[D + public fun getDimension ()I + public final fun getLower ()Lspace/kscience/kmath/structures/Buffer; + public fun getLowerBound (I)D + public final fun getUpper ()Lspace/kscience/kmath/structures/Buffer; + public fun getUpperBound (I)D + public fun volume ()D +} + +public final class space/kscience/kmath/domains/UnconstrainedDomain : space/kscience/kmath/domains/DoubleDomain { + public fun (I)V + public fun contains (Lspace/kscience/kmath/structures/Buffer;)Z + public fun getDimension ()I + public fun getLowerBound (I)D + public fun getUpperBound (I)D + public fun volume ()D +} + public abstract interface class space/kscience/kmath/expressions/AutoDiffProcessor { public abstract fun differentiate (Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/DifferentiableExpression; } @@ -31,6 +104,140 @@ public class space/kscience/kmath/expressions/AutoDiffValue { public final fun getValue ()Ljava/lang/Object; } +public abstract interface class space/kscience/kmath/expressions/DS { + public abstract fun getData ()Lspace/kscience/kmath/structures/Buffer; + public abstract fun getDerivativeAlgebra ()Lspace/kscience/kmath/expressions/DSAlgebra; +} + +public abstract class space/kscience/kmath/expressions/DSAlgebra : space/kscience/kmath/expressions/ExpressionAlgebra, space/kscience/kmath/expressions/SymbolIndexer { + public fun (Lspace/kscience/kmath/operations/Ring;ILjava/util/Map;)V + protected final fun DS (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/DSAlgebra$DSSymbol; + public final fun bindSymbol (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/DSAlgebra$DSSymbol; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/DSAlgebra$DSSymbol; + public final fun bindSymbolOrNull (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/DSAlgebra$DSSymbol; + public synthetic fun const (Ljava/lang/Object;)Ljava/lang/Object; + public fun const (Ljava/lang/Object;)Lspace/kscience/kmath/expressions/DS; + public final fun derivative (Lspace/kscience/kmath/expressions/DS;Ljava/util/List;)Ljava/lang/Object; + public final fun derivative (Lspace/kscience/kmath/expressions/DS;[Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; + public final fun getAlgebra ()Lspace/kscience/kmath/operations/Ring; + public final fun getCompiler ()Lspace/kscience/kmath/expressions/DSCompiler; + public final fun getOrder ()I + public fun getSymbols ()Ljava/util/List; + public final fun ofDerivatives ([Ljava/lang/Object;)Lspace/kscience/kmath/expressions/DS; + public final fun variable (ILjava/lang/Object;)Lspace/kscience/kmath/expressions/DS; +} + +public final class space/kscience/kmath/expressions/DSAlgebra$DSSymbol : space/kscience/kmath/expressions/DS, space/kscience/kmath/expressions/Symbol { + public fun getData ()Lspace/kscience/kmath/structures/Buffer; + public fun getDerivativeAlgebra ()Lspace/kscience/kmath/expressions/DSAlgebra; + public fun getIdentity ()Ljava/lang/String; +} + +public final class space/kscience/kmath/expressions/DSAlgebraKt { + public static final fun derivative (Lspace/kscience/kmath/expressions/DS;Ljava/util/List;)Ljava/lang/Object; + public static final fun derivative (Lspace/kscience/kmath/expressions/DS;[Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; + public static final fun getAutodiff (Lkotlin/jvm/internal/DoubleCompanionObject;)Lspace/kscience/kmath/expressions/DSFieldProcessor; + public static final fun getValue (Lspace/kscience/kmath/expressions/DS;)Ljava/lang/Object; +} + +public final class space/kscience/kmath/expressions/DSCompiler { + public final fun getAlgebra ()Lspace/kscience/kmath/operations/Algebra; + public final fun getFreeParameters ()I + public final fun getOrder ()I + public final fun getPartialDerivativeIndex ([I)I + public final fun getPartialDerivativeOrders (I)[I + public final fun getSize ()I + public final fun getSizes ()[[I +} + +public final class space/kscience/kmath/expressions/DSField : space/kscience/kmath/expressions/DSRing, space/kscience/kmath/operations/ExtendedField { + public fun (Lspace/kscience/kmath/operations/ExtendedField;ILjava/util/Map;)V + public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object; + public fun acos (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object; + public fun acosh (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object; + public fun asin (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object; + public fun asinh (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object; + public fun atan (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object; + public fun atanh (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; + public fun cos (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; + public fun cosh (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun divide (Lspace/kscience/kmath/expressions/DS;Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; + public fun exp (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; + public fun ln (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; + public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun power (Lspace/kscience/kmath/expressions/DS;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/DS; + public final fun power (Lspace/kscience/kmath/expressions/DS;Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; + public fun sin (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; + public fun sinh (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; + public fun sqrt (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; + public fun tan (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; + public fun tanh (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; +} + +public final class space/kscience/kmath/expressions/DSFieldExpression : space/kscience/kmath/expressions/DifferentiableExpression { + public fun (Lspace/kscience/kmath/operations/ExtendedField;Lkotlin/jvm/functions/Function1;)V + public fun derivativeOrNull (Ljava/util/List;)Lspace/kscience/kmath/expressions/Expression; + public final fun getAlgebra ()Lspace/kscience/kmath/operations/ExtendedField; + public final fun getFunction ()Lkotlin/jvm/functions/Function1; + public fun invoke (Ljava/util/Map;)Ljava/lang/Object; +} + +public final class space/kscience/kmath/expressions/DSFieldProcessor : space/kscience/kmath/expressions/AutoDiffProcessor { + public fun (Lspace/kscience/kmath/operations/ExtendedField;)V + public fun differentiate (Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/DifferentiableExpression; + public final fun getAlgebra ()Lspace/kscience/kmath/operations/ExtendedField; +} + +public class space/kscience/kmath/expressions/DSRing : space/kscience/kmath/expressions/DSAlgebra, space/kscience/kmath/operations/NumbersAddOps, space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/Ring, space/kscience/kmath/operations/ScaleOperations { + public fun (Lspace/kscience/kmath/operations/Ring;ILjava/util/Map;)V + public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun add (Lspace/kscience/kmath/expressions/DS;Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/DSAlgebra$DSSymbol; + public final fun getElementBufferFactory ()Lspace/kscience/kmath/structures/MutableBufferFactory; + public synthetic fun getOne ()Ljava/lang/Object; + public fun getOne ()Lspace/kscience/kmath/expressions/DS; + public synthetic fun getZero ()Ljava/lang/Object; + public fun getZero ()Lspace/kscience/kmath/expressions/DS; + protected final fun mapData (Lspace/kscience/kmath/expressions/DS;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/expressions/DS; + protected final fun mapDataIndexed (Lspace/kscience/kmath/expressions/DS;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun minus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun multiply (Lspace/kscience/kmath/expressions/DS;Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; + public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun plus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun plus (Ljava/lang/Number;Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun plus (Lspace/kscience/kmath/expressions/DS;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; + public fun scale (Lspace/kscience/kmath/expressions/DS;D)Lspace/kscience/kmath/expressions/DS; + protected final fun transformDataBuffer (Lspace/kscience/kmath/expressions/DS;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/expressions/DS; + public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryMinus (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; +} + public final class space/kscience/kmath/expressions/DerivationResult { public fun (Ljava/lang/Object;Ljava/util/Map;Lspace/kscience/kmath/operations/Field;)V public final fun derivative (Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; @@ -39,6 +246,22 @@ public final class space/kscience/kmath/expressions/DerivationResult { public final fun getValue ()Ljava/lang/Object; } +public final class space/kscience/kmath/expressions/DerivativeStructureRingExpression : space/kscience/kmath/expressions/DifferentiableExpression { + public fun (Lspace/kscience/kmath/operations/Ring;Lspace/kscience/kmath/structures/MutableBufferFactory;Lkotlin/jvm/functions/Function1;)V + public synthetic fun (Lspace/kscience/kmath/operations/Ring;Lspace/kscience/kmath/structures/MutableBufferFactory;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun derivativeOrNull (Ljava/util/List;)Lspace/kscience/kmath/expressions/Expression; + public final fun getAlgebra ()Lspace/kscience/kmath/operations/Ring; + public final fun getElementBufferFactory ()Lspace/kscience/kmath/structures/MutableBufferFactory; + public final fun getFunction ()Lkotlin/jvm/functions/Function1; + public fun invoke (Ljava/util/Map;)Ljava/lang/Object; +} + +public final class space/kscience/kmath/expressions/DiffExpressionWithDefault : space/kscience/kmath/expressions/DifferentiableExpression { + public fun (Lspace/kscience/kmath/expressions/DifferentiableExpression;Ljava/util/Map;)V + public fun derivativeOrNull (Ljava/util/List;)Lspace/kscience/kmath/expressions/Expression; + public fun invoke (Ljava/util/Map;)Ljava/lang/Object; +} + public abstract interface class space/kscience/kmath/expressions/DifferentiableExpression : space/kscience/kmath/expressions/Expression { public abstract fun derivativeOrNull (Ljava/util/List;)Lspace/kscience/kmath/expressions/Expression; } @@ -52,6 +275,17 @@ public final class space/kscience/kmath/expressions/DifferentiableExpressionKt { public static final fun derivative (Lspace/kscience/kmath/expressions/SpecialDifferentiableExpression;[Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/Expression; } +public abstract interface class space/kscience/kmath/expressions/DoubleExpression : space/kscience/kmath/expressions/Expression { + public static final field Companion Lspace/kscience/kmath/expressions/DoubleExpression$Companion; + public abstract fun getIndexer ()Lspace/kscience/kmath/expressions/SymbolIndexer; + public fun invoke (Ljava/util/Map;)Ljava/lang/Double; + public synthetic fun invoke (Ljava/util/Map;)Ljava/lang/Object; + public abstract fun invoke ([D)D +} + +public final class space/kscience/kmath/expressions/DoubleExpression$Companion { +} + public abstract interface class space/kscience/kmath/expressions/Expression { public abstract fun invoke (Ljava/util/Map;)Ljava/lang/Object; } @@ -64,7 +298,23 @@ public final class space/kscience/kmath/expressions/ExpressionKt { public static final fun callByString (Lspace/kscience/kmath/expressions/Expression;[Lkotlin/Pair;)Ljava/lang/Object; public static final fun callBySymbol (Lspace/kscience/kmath/expressions/Expression;[Lkotlin/Pair;)Ljava/lang/Object; public static final fun getBinding (Lspace/kscience/kmath/expressions/ExpressionAlgebra;)Lkotlin/properties/ReadOnlyProperty; + public static final fun invoke (Lspace/kscience/kmath/expressions/DoubleExpression;)D + public static final fun invoke (Lspace/kscience/kmath/expressions/DoubleExpression;[D)D public static final fun invoke (Lspace/kscience/kmath/expressions/Expression;)Ljava/lang/Object; + public static final fun invoke (Lspace/kscience/kmath/expressions/IntExpression;)I + public static final fun invoke (Lspace/kscience/kmath/expressions/IntExpression;[I)I + public static final fun invoke (Lspace/kscience/kmath/expressions/LongExpression;)J + public static final fun invoke (Lspace/kscience/kmath/expressions/LongExpression;[J)J +} + +public final class space/kscience/kmath/expressions/ExpressionWithDefault : space/kscience/kmath/expressions/Expression { + public fun (Lspace/kscience/kmath/expressions/Expression;Ljava/util/Map;)V + public fun invoke (Ljava/util/Map;)Ljava/lang/Object; +} + +public final class space/kscience/kmath/expressions/ExpressionWithDefaultKt { + public static final fun withDefaultArgs (Lspace/kscience/kmath/expressions/DifferentiableExpression;Ljava/util/Map;)Lspace/kscience/kmath/expressions/DiffExpressionWithDefault; + public static final fun withDefaultArgs (Lspace/kscience/kmath/expressions/Expression;Ljava/util/Map;)Lspace/kscience/kmath/expressions/ExpressionWithDefault; } public abstract class space/kscience/kmath/expressions/FirstDerivativeExpression : space/kscience/kmath/expressions/DifferentiableExpression { @@ -160,6 +410,28 @@ public class space/kscience/kmath/expressions/FunctionalExpressionRing : space/k public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } +public abstract interface class space/kscience/kmath/expressions/IntExpression : space/kscience/kmath/expressions/Expression { + public static final field Companion Lspace/kscience/kmath/expressions/IntExpression$Companion; + public abstract fun getIndexer ()Lspace/kscience/kmath/expressions/SymbolIndexer; + public fun invoke (Ljava/util/Map;)Ljava/lang/Integer; + public synthetic fun invoke (Ljava/util/Map;)Ljava/lang/Object; + public abstract fun invoke ([I)I +} + +public final class space/kscience/kmath/expressions/IntExpression$Companion { +} + +public abstract interface class space/kscience/kmath/expressions/LongExpression : space/kscience/kmath/expressions/Expression { + public static final field Companion Lspace/kscience/kmath/expressions/LongExpression$Companion; + public abstract fun getIndexer ()Lspace/kscience/kmath/expressions/SymbolIndexer; + public fun invoke (Ljava/util/Map;)Ljava/lang/Long; + public synthetic fun invoke (Ljava/util/Map;)Ljava/lang/Object; + public abstract fun invoke ([J)J +} + +public final class space/kscience/kmath/expressions/LongExpression$Companion { +} + public abstract interface class space/kscience/kmath/expressions/MST { } @@ -318,6 +590,22 @@ public final class space/kscience/kmath/expressions/MstGroup : space/kscience/km public fun unaryPlus (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; } +public final class space/kscience/kmath/expressions/MstLogicAlgebra : space/kscience/kmath/operations/LogicAlgebra { + public static final field INSTANCE Lspace/kscience/kmath/expressions/MstLogicAlgebra; + public synthetic fun and (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun and (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun const (Z)Ljava/lang/Object; + public fun const (Z)Lspace/kscience/kmath/expressions/Symbol; + public synthetic fun not (Ljava/lang/Object;)Ljava/lang/Object; + public fun not (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun or (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun or (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; + public synthetic fun xor (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun xor (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; +} + public final class space/kscience/kmath/expressions/MstNumericAlgebra : space/kscience/kmath/operations/NumericAlgebra { public static final field INSTANCE Lspace/kscience/kmath/expressions/MstNumericAlgebra; public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; @@ -356,6 +644,35 @@ public final class space/kscience/kmath/expressions/MstRing : space/kscience/kma public fun unaryPlus (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; } +public final class space/kscience/kmath/expressions/NamedMatrix : space/kscience/kmath/nd/Structure2D { + public static final field Companion Lspace/kscience/kmath/expressions/NamedMatrix$Companion; + public fun (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/expressions/SymbolIndexer;)V + public fun elements ()Lkotlin/sequences/Sequence; + public fun get (II)Ljava/lang/Object; + public final fun get (Lspace/kscience/kmath/expressions/Symbol;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; + public fun get ([I)Ljava/lang/Object; + public fun getColNum ()I + public fun getColumns ()Ljava/util/List; + public fun getDimension ()I + public synthetic fun getFeature (Lkotlin/reflect/KClass;)Ljava/lang/Object; + public fun getFeature (Lkotlin/reflect/KClass;)Lspace/kscience/kmath/nd/StructureFeature; + public final fun getIndexer ()Lspace/kscience/kmath/expressions/SymbolIndexer; + public fun getIndices ()Lspace/kscience/kmath/nd/ShapeIndexer; + public fun getRowNum ()I + public fun getRows ()Ljava/util/List; + public fun getShape-IIYLAfE ()[I + public final fun getValues ()Lspace/kscience/kmath/nd/Structure2D; +} + +public final class space/kscience/kmath/expressions/NamedMatrix$Companion { + public final fun toStringWithSymbols (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/expressions/SymbolIndexer;)Ljava/lang/String; +} + +public final class space/kscience/kmath/expressions/NamedMatrixKt { + public static final fun named (Lspace/kscience/kmath/nd/Structure2D;Ljava/util/List;)Lspace/kscience/kmath/expressions/NamedMatrix; + public static final fun named (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/expressions/SymbolIndexer;)Lspace/kscience/kmath/expressions/NamedMatrix; +} + public final class space/kscience/kmath/expressions/SimpleAutoDiffExpression : space/kscience/kmath/expressions/FirstDerivativeExpression { public fun (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function1;)V public fun derivativeOrNull (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/Expression; @@ -461,13 +778,22 @@ public final class space/kscience/kmath/expressions/SimpleAutoDiffKt { public static final fun tanh (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; } -public abstract interface class space/kscience/kmath/expressions/SpecialDifferentiableExpression : space/kscience/kmath/expressions/DifferentiableExpression { - public abstract fun derivativeOrNull (Ljava/util/List;)Lspace/kscience/kmath/expressions/Expression; +public final class space/kscience/kmath/expressions/SimpleSymbolIndexer : space/kscience/kmath/expressions/SymbolIndexer { + public static final synthetic fun box-impl (Ljava/util/List;)Lspace/kscience/kmath/expressions/SimpleSymbolIndexer; + public static fun constructor-impl (Ljava/util/List;)Ljava/util/List; + public fun equals (Ljava/lang/Object;)Z + public static fun equals-impl (Ljava/util/List;Ljava/lang/Object;)Z + public static final fun equals-impl0 (Ljava/util/List;Ljava/util/List;)Z + public fun getSymbols ()Ljava/util/List; + public fun hashCode ()I + public static fun hashCode-impl (Ljava/util/List;)I + public fun toString ()Ljava/lang/String; + public static fun toString-impl (Ljava/util/List;)Ljava/lang/String; + public final synthetic fun unbox-impl ()Ljava/util/List; } -public final class space/kscience/kmath/expressions/SpecialExpressionsKt { - public static final fun chiSquaredExpression (Lspace/kscience/kmath/expressions/AutoDiffProcessor;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/expressions/DifferentiableExpression; - public static final fun genericChiSquaredExpression (Lspace/kscience/kmath/expressions/AutoDiffProcessor;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/expressions/DifferentiableExpression; +public abstract interface class space/kscience/kmath/expressions/SpecialDifferentiableExpression : space/kscience/kmath/expressions/DifferentiableExpression { + public abstract fun derivativeOrNull (Ljava/util/List;)Lspace/kscience/kmath/expressions/Expression; } public abstract interface class space/kscience/kmath/expressions/Symbol : space/kscience/kmath/expressions/MST { @@ -484,7 +810,25 @@ public final class space/kscience/kmath/expressions/Symbol$Companion { public final fun getZError ()Lspace/kscience/kmath/expressions/Symbol; } +public abstract interface class space/kscience/kmath/expressions/SymbolIndexer { + public fun get (Ljava/util/List;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; + public fun get (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/expressions/Symbol;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; + public fun get (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; + public fun get ([DLspace/kscience/kmath/expressions/Symbol;)D + public fun get ([Ljava/lang/Object;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; + public abstract fun getSymbols ()Ljava/util/List; + public fun indexOf (Lspace/kscience/kmath/expressions/Symbol;)I + public fun toDoubleArray (Ljava/util/Map;)[D + public fun toList (Ljava/util/Map;)Ljava/util/List; + public fun toMap (Lspace/kscience/kmath/structures/Buffer;)Ljava/util/Map; + public fun toMap ([D)Ljava/util/Map; + public fun toPoint (Ljava/util/Map;Lspace/kscience/kmath/structures/BufferFactory;)Lspace/kscience/kmath/structures/Buffer; + public fun toPoint-Udx-57Q (Ljava/util/Map;)[D +} + public final class space/kscience/kmath/expressions/SymbolIndexerKt { + public static final fun withSymbols (Ljava/util/Collection;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public static final fun withSymbols ([Lspace/kscience/kmath/expressions/Symbol;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; } public final class space/kscience/kmath/expressions/SymbolKt { @@ -510,7 +854,7 @@ public final class space/kscience/kmath/linear/BufferedLinearSpace : space/kscie } public final class space/kscience/kmath/linear/BufferedLinearSpaceKt { - public static final fun linearSpace (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/linear/BufferedLinearSpace; + public static final fun getLinearSpace (Lspace/kscience/kmath/operations/Ring;)Lspace/kscience/kmath/linear/BufferedLinearSpace; } public abstract interface class space/kscience/kmath/linear/CholeskyDecompositionFeature : space/kscience/kmath/linear/MatrixFeature { @@ -581,6 +925,7 @@ public abstract interface class space/kscience/kmath/linear/LinearSpace { public static final field Companion Lspace/kscience/kmath/linear/LinearSpace$Companion; public abstract fun buildMatrix (IILkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/Structure2D; public abstract fun buildVector (ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; + public fun computeFeature (Lspace/kscience/kmath/nd/Structure2D;Lkotlin/reflect/KClass;)Lspace/kscience/kmath/nd/StructureFeature; public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public abstract fun getElementAlgebra ()Lspace/kscience/kmath/operations/Ring; @@ -597,9 +942,7 @@ public abstract interface class space/kscience/kmath/linear/LinearSpace { } public final class space/kscience/kmath/linear/LinearSpace$Companion { - public final fun buffered (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/linear/LinearSpace; - public static synthetic fun buffered$default (Lspace/kscience/kmath/linear/LinearSpace$Companion;Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lspace/kscience/kmath/linear/LinearSpace; - public final fun getDouble ()Lspace/kscience/kmath/linear/LinearSpace; + public final fun buffered (Lspace/kscience/kmath/operations/Ring;)Lspace/kscience/kmath/linear/LinearSpace; } public final class space/kscience/kmath/linear/LinearSpaceKt { @@ -628,11 +971,11 @@ public abstract interface class space/kscience/kmath/linear/LupDecompositionFeat public final class space/kscience/kmath/linear/LupDecompositionKt { public static final fun abs (Lspace/kscience/kmath/linear/LinearSpace;Ljava/lang/Comparable;)Ljava/lang/Comparable; - public static final fun lup (Lspace/kscience/kmath/linear/LinearSpace;Lkotlin/jvm/functions/Function2;Lspace/kscience/kmath/nd/Structure2D;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/linear/LupDecomposition; public static final fun lup (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;D)Lspace/kscience/kmath/linear/LupDecomposition; + public static final fun lup (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/structures/MutableBufferFactory;Lspace/kscience/kmath/nd/Structure2D;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/linear/LupDecomposition; public static synthetic fun lup$default (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/Structure2D;DILjava/lang/Object;)Lspace/kscience/kmath/linear/LupDecomposition; public static final fun lupSolver (Lspace/kscience/kmath/linear/LinearSpace;D)Lspace/kscience/kmath/linear/LinearSolver; - public static final fun lupSolver (Lspace/kscience/kmath/linear/LinearSpace;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/linear/LinearSolver; + public static final fun lupSolver (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/structures/MutableBufferFactory;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/linear/LinearSolver; public static synthetic fun lupSolver$default (Lspace/kscience/kmath/linear/LinearSpace;DILjava/lang/Object;)Lspace/kscience/kmath/linear/LinearSolver; } @@ -647,9 +990,11 @@ public final class space/kscience/kmath/linear/MatrixBuilder { public final class space/kscience/kmath/linear/MatrixBuilderKt { public static final fun column (Lspace/kscience/kmath/linear/LinearSpace;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/Structure2D; public static final fun column (Lspace/kscience/kmath/linear/LinearSpace;[Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; + public static final fun matrix (Lspace/kscience/kmath/linear/LinearSpace;II)Lspace/kscience/kmath/linear/MatrixBuilder; public static final fun row (Lspace/kscience/kmath/linear/LinearSpace;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/Structure2D; public static final fun row (Lspace/kscience/kmath/linear/LinearSpace;[Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; public static final fun symmetric (Lspace/kscience/kmath/linear/MatrixBuilder;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/Structure2D; + public static final fun vector (Lspace/kscience/kmath/linear/LinearSpace;[Ljava/lang/Object;)Lspace/kscience/kmath/structures/Buffer; } public abstract interface class space/kscience/kmath/linear/MatrixFeature : space/kscience/kmath/nd/StructureFeature { @@ -673,7 +1018,7 @@ public final class space/kscience/kmath/linear/MatrixWrapper : space/kscience/km public final fun getOrigin ()Lspace/kscience/kmath/nd/Structure2D; public fun getRowNum ()I public fun getRows ()Ljava/util/List; - public fun getShape ()[I + public fun getShape-IIYLAfE ()[I public fun toString ()Ljava/lang/String; } @@ -726,7 +1071,7 @@ public final class space/kscience/kmath/linear/VirtualMatrix : space/kscience/km public fun getColNum ()I public final fun getGenerator ()Lkotlin/jvm/functions/Function2; public fun getRowNum ()I - public fun getShape ()[I + public fun getShape-IIYLAfE ()[I } public final class space/kscience/kmath/linear/VirtualMatrixKt { @@ -737,6 +1082,11 @@ public final class space/kscience/kmath/linear/ZeroFeature : space/kscience/kmat public static final field INSTANCE Lspace/kscience/kmath/linear/ZeroFeature; } +public final class space/kscience/kmath/misc/CollectionsKt { + public static final fun zipWithNextCircular (Ljava/util/List;)Ljava/util/List; + public static final fun zipWithNextCircular (Ljava/util/List;Lkotlin/jvm/functions/Function2;)Ljava/util/List; +} + public final class space/kscience/kmath/misc/CumulativeKt { public static final fun cumulative (Ljava/lang/Iterable;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Iterable; public static final fun cumulative (Ljava/util/Iterator;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/util/Iterator; @@ -745,6 +1095,7 @@ public final class space/kscience/kmath/misc/CumulativeKt { public static final fun cumulativeSum (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Ring;)Ljava/lang/Iterable; public static final fun cumulativeSum (Ljava/util/List;Lspace/kscience/kmath/operations/Ring;)Ljava/util/List; public static final fun cumulativeSum (Lkotlin/sequences/Sequence;Lspace/kscience/kmath/operations/Ring;)Lkotlin/sequences/Sequence; + public static final fun cumulativeSum (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/operations/Ring;)Lspace/kscience/kmath/structures/Buffer; public static final fun cumulativeSumOfDouble (Ljava/lang/Iterable;)Ljava/lang/Iterable; public static final fun cumulativeSumOfDouble (Ljava/util/List;)Ljava/util/List; public static final fun cumulativeSumOfDouble (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence; @@ -811,11 +1162,12 @@ public final class space/kscience/kmath/misc/NumbersJVMKt { public static final fun toIntExact (J)I } -public abstract interface annotation class space/kscience/kmath/misc/PerformancePitfall : java/lang/annotation/Annotation { - public abstract fun message ()Ljava/lang/String; -} - public final class space/kscience/kmath/misc/SortingKt { + public static final fun indicesSorted (Lspace/kscience/kmath/structures/Buffer;)[I + public static final fun indicesSortedBy (Lspace/kscience/kmath/structures/Buffer;Lkotlin/jvm/functions/Function1;)[I + public static final fun indicesSortedByDescending (Lspace/kscience/kmath/structures/Buffer;Lkotlin/jvm/functions/Function1;)[I + public static final fun indicesSortedDescending (Lspace/kscience/kmath/structures/Buffer;)[I + public static final fun indicesSortedWith (Lspace/kscience/kmath/structures/Buffer;Ljava/util/Comparator;)[I public static final fun requireSorted (Lspace/kscience/kmath/structures/Buffer;)V public static final fun sorted (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public static final fun sortedBy (Lspace/kscience/kmath/structures/Buffer;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; @@ -823,16 +1175,14 @@ public final class space/kscience/kmath/misc/SortingKt { public static final fun sortedDescending (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; } -public abstract interface annotation class space/kscience/kmath/misc/UnstableKMathAPI : java/lang/annotation/Annotation { -} - public abstract interface class space/kscience/kmath/nd/AlgebraND : space/kscience/kmath/operations/Algebra { public static final field Companion Lspace/kscience/kmath/nd/AlgebraND$Companion; public abstract fun getElementAlgebra ()Lspace/kscience/kmath/operations/Algebra; + public fun getFeature (Lspace/kscience/kmath/nd/StructureND;Lkotlin/reflect/KClass;)Lspace/kscience/kmath/nd/StructureFeature; public fun invoke (Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; public fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; - public abstract fun structureND ([ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; + public abstract fun structureND-qL90JFI ([ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; public fun zip (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; } @@ -840,17 +1190,13 @@ public final class space/kscience/kmath/nd/AlgebraND$Companion { } public final class space/kscience/kmath/nd/AlgebraNDExtentionsKt { - public static final fun one (Lspace/kscience/kmath/nd/AlgebraND;[I)Lspace/kscience/kmath/nd/StructureND; + public static final fun one-waz_sdI (Lspace/kscience/kmath/nd/AlgebraND;[I)Lspace/kscience/kmath/nd/StructureND; public static final fun oneVarArg (Lspace/kscience/kmath/nd/AlgebraND;I[I)Lspace/kscience/kmath/nd/StructureND; public static final fun structureND (Lspace/kscience/kmath/nd/AlgebraND;I[ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; - public static final fun zero (Lspace/kscience/kmath/nd/AlgebraND;[I)Lspace/kscience/kmath/nd/StructureND; + public static final fun zero-waz_sdI (Lspace/kscience/kmath/nd/AlgebraND;[I)Lspace/kscience/kmath/nd/StructureND; public static final fun zeroVarArg (Lspace/kscience/kmath/nd/AlgebraND;I[I)Lspace/kscience/kmath/nd/StructureND; } -public final class space/kscience/kmath/nd/AlgebraNDKt { - public static final fun Shape (I[I)[I -} - public abstract interface class space/kscience/kmath/nd/BufferAlgebraND : space/kscience/kmath/nd/AlgebraND { public static final field Companion Lspace/kscience/kmath/nd/BufferAlgebraND$Companion; public abstract fun getBufferAlgebra ()Lspace/kscience/kmath/operations/BufferAlgebra; @@ -860,8 +1206,8 @@ public abstract interface class space/kscience/kmath/nd/BufferAlgebraND : space/ public synthetic fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; public fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; - public fun structureND ([ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND; - public synthetic fun structureND ([ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; + public fun structureND-qL90JFI ([ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND; + public synthetic fun structureND-qL90JFI ([ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; public fun toBufferND (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/BufferND; public fun zip (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/BufferND; public synthetic fun zip (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; @@ -885,19 +1231,22 @@ public class space/kscience/kmath/nd/BufferND : space/kscience/kmath/nd/Structur public fun get ([I)Ljava/lang/Object; public fun getBuffer ()Lspace/kscience/kmath/structures/Buffer; public fun getIndices ()Lspace/kscience/kmath/nd/ShapeIndexer; - public fun getShape ()[I + public fun getShape-IIYLAfE ()[I public fun toString ()Ljava/lang/String; } public final class space/kscience/kmath/nd/BufferNDKt { - public static final fun mapToBuffer (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/BufferND; + public static final fun BufferND-bYNkpeI ([ILspace/kscience/kmath/structures/BufferFactory;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/BufferND; + public static synthetic fun BufferND-bYNkpeI$default ([ILspace/kscience/kmath/structures/BufferFactory;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/BufferND; + public static final fun MutableBufferND-bYNkpeI ([ILspace/kscience/kmath/structures/MutableBufferFactory;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/MutableBufferND; + public static synthetic fun MutableBufferND-bYNkpeI$default ([ILspace/kscience/kmath/structures/MutableBufferFactory;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/MutableBufferND; } public class space/kscience/kmath/nd/BufferedFieldOpsND : space/kscience/kmath/nd/BufferedRingOpsND, space/kscience/kmath/nd/FieldOpsND { public fun (Lspace/kscience/kmath/operations/BufferAlgebra;Lkotlin/jvm/functions/Function1;)V public synthetic fun (Lspace/kscience/kmath/operations/BufferAlgebra;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public fun (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)V - public synthetic fun (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function1;)V + public synthetic fun (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; public fun scale (Lspace/kscience/kmath/nd/StructureND;D)Lspace/kscience/kmath/nd/StructureND; } @@ -916,29 +1265,30 @@ public class space/kscience/kmath/nd/BufferedRingOpsND : space/kscience/kmath/nd public synthetic fun (Lspace/kscience/kmath/operations/BufferAlgebra;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V } -public final class space/kscience/kmath/nd/DefaultStrides : space/kscience/kmath/nd/Strides { - public static final field Companion Lspace/kscience/kmath/nd/DefaultStrides$Companion; +public final class space/kscience/kmath/nd/ColumnStrides : space/kscience/kmath/nd/Strides { + public static final field Companion Lspace/kscience/kmath/nd/ColumnStrides$Companion; public synthetic fun ([ILkotlin/jvm/internal/DefaultConstructorMarker;)V public fun equals (Ljava/lang/Object;)Z public fun getLinearSize ()I - public fun getShape ()[I - public fun getStrides ()[I + public fun getShape-IIYLAfE ()[I public fun hashCode ()I public fun index (I)[I } -public final class space/kscience/kmath/nd/DefaultStrides$Companion { - public final fun invoke ([I)Lspace/kscience/kmath/nd/Strides; +public final class space/kscience/kmath/nd/ColumnStrides$Companion { } -public final class space/kscience/kmath/nd/DoubleBufferND : space/kscience/kmath/nd/BufferND { +public final class space/kscience/kmath/nd/DoubleBufferND : space/kscience/kmath/nd/MutableBufferND, space/kscience/kmath/nd/MutableStructureNDOfDouble { public synthetic fun (Lspace/kscience/kmath/nd/ShapeIndexer;[DLkotlin/jvm/internal/DefaultConstructorMarker;)V public synthetic fun getBuffer ()Lspace/kscience/kmath/structures/Buffer; + public synthetic fun getBuffer ()Lspace/kscience/kmath/structures/MutableBuffer; public fun getBuffer-Dv3HvWU ()[D + public fun getDouble ([I)D + public fun setDouble ([ID)V } public final class space/kscience/kmath/nd/DoubleFieldND : space/kscience/kmath/nd/DoubleFieldOpsND, space/kscience/kmath/nd/FieldND, space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/NumbersAddOps { - public fun ([I)V + public synthetic fun ([ILkotlin/jvm/internal/DefaultConstructorMarker;)V public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object; public fun acosh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/DoubleBufferND; public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object; @@ -947,13 +1297,14 @@ public final class space/kscience/kmath/nd/DoubleFieldND : space/kscience/kmath/ public fun atanh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/DoubleBufferND; public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; public fun cosh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/DoubleBufferND; - public fun getShape ()[I + public fun getShape-IIYLAfE ()[I public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/DoubleBufferND; public synthetic fun power (Ljava/lang/Object;I)Ljava/lang/Object; public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; public fun power (Lspace/kscience/kmath/nd/StructureND;I)Lspace/kscience/kmath/nd/DoubleBufferND; public fun power (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/DoubleBufferND; + public synthetic fun power (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun power-Qn1smSk (Ljava/lang/Object;I)Ljava/lang/Object; public fun power-Qn1smSk (Lspace/kscience/kmath/nd/StructureND;I)Lspace/kscience/kmath/nd/DoubleBufferND; public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; @@ -965,6 +1316,8 @@ public final class space/kscience/kmath/nd/DoubleFieldND : space/kscience/kmath/ public final class space/kscience/kmath/nd/DoubleFieldNDKt { public static final fun getNdAlgebra (Lspace/kscience/kmath/operations/DoubleField;)Lspace/kscience/kmath/nd/DoubleFieldOpsND; public static final fun ndAlgebra (Lspace/kscience/kmath/operations/DoubleField;[I)Lspace/kscience/kmath/nd/DoubleFieldND; + public static final fun ndAlgebra-waz_sdI (Lspace/kscience/kmath/operations/DoubleField;[I)Lspace/kscience/kmath/nd/DoubleFieldND; + public static final fun withNdAlgebra (Lspace/kscience/kmath/operations/DoubleField;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object; } public abstract class space/kscience/kmath/nd/DoubleFieldOpsND : space/kscience/kmath/nd/BufferedFieldOpsND, space/kscience/kmath/operations/ExtendedFieldOps, space/kscience/kmath/operations/ScaleOperations { @@ -1021,6 +1374,8 @@ public abstract class space/kscience/kmath/nd/DoubleFieldOpsND : space/kscience/ public fun plus (Lspace/kscience/kmath/nd/StructureND;D)Lspace/kscience/kmath/nd/DoubleBufferND; public synthetic fun plus (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; public fun plus (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/DoubleBufferND; + public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun power (Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Number;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; public fun scale (Lspace/kscience/kmath/nd/StructureND;D)Lspace/kscience/kmath/nd/DoubleBufferND; public synthetic fun scale (Lspace/kscience/kmath/nd/StructureND;D)Lspace/kscience/kmath/nd/StructureND; @@ -1028,9 +1383,9 @@ public abstract class space/kscience/kmath/nd/DoubleFieldOpsND : space/kscience/ public fun sin (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/DoubleBufferND; public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; public fun sinh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/DoubleBufferND; - public synthetic fun structureND ([ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND; - public fun structureND ([ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/DoubleBufferND; - public synthetic fun structureND ([ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; + public synthetic fun structureND-qL90JFI ([ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND; + public fun structureND-qL90JFI ([ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/DoubleBufferND; + public synthetic fun structureND-qL90JFI ([ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; public fun tan (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/DoubleBufferND; public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; @@ -1087,7 +1442,41 @@ public abstract interface class space/kscience/kmath/nd/GroupOpsND : space/kscie public final class space/kscience/kmath/nd/GroupOpsND$Companion { } -public final class space/kscience/kmath/nd/MutableBufferND : space/kscience/kmath/nd/BufferND, space/kscience/kmath/nd/MutableStructureND { +public final class space/kscience/kmath/nd/IndexOutOfShapeException : java/lang/RuntimeException { + public synthetic fun ([I[ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun getIndex ()[I + public final fun getShape-IIYLAfE ()[I +} + +public final class space/kscience/kmath/nd/IntBufferND : space/kscience/kmath/nd/MutableBufferND { + public synthetic fun (Lspace/kscience/kmath/nd/ShapeIndexer;[ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun getBuffer ()Lspace/kscience/kmath/structures/Buffer; + public synthetic fun getBuffer ()Lspace/kscience/kmath/structures/MutableBuffer; + public fun getBuffer-ir4F4A8 ()[I +} + +public final class space/kscience/kmath/nd/IntRingND : space/kscience/kmath/nd/IntRingOpsND, space/kscience/kmath/nd/RingND, space/kscience/kmath/operations/NumbersAddOps { + public synthetic fun ([ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun getShape-IIYLAfE ()[I + public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; + public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/BufferND; +} + +public final class space/kscience/kmath/nd/IntRingNDKt { + public static final fun withNdAlgebra (Lspace/kscience/kmath/operations/IntRing;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object; +} + +public abstract class space/kscience/kmath/nd/IntRingOpsND : space/kscience/kmath/nd/BufferedRingOpsND { + public static final field Companion Lspace/kscience/kmath/nd/IntRingOpsND$Companion; + public synthetic fun structureND-qL90JFI ([ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/BufferND; + public fun structureND-qL90JFI ([ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/IntBufferND; + public synthetic fun structureND-qL90JFI ([ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; +} + +public final class space/kscience/kmath/nd/IntRingOpsND$Companion : space/kscience/kmath/nd/IntRingOpsND { +} + +public class space/kscience/kmath/nd/MutableBufferND : space/kscience/kmath/nd/BufferND, space/kscience/kmath/nd/MutableStructureND { public fun (Lspace/kscience/kmath/nd/ShapeIndexer;Lspace/kscience/kmath/structures/MutableBuffer;)V public synthetic fun getBuffer ()Lspace/kscience/kmath/structures/Buffer; public fun getBuffer ()Lspace/kscience/kmath/structures/MutableBuffer; @@ -1108,6 +1497,46 @@ public abstract interface class space/kscience/kmath/nd/MutableStructureND : spa public abstract fun set ([ILjava/lang/Object;)V } +public abstract interface class space/kscience/kmath/nd/MutableStructureNDOfDouble : space/kscience/kmath/nd/MutableStructureND, space/kscience/kmath/nd/StructureNDOfDouble { + public abstract fun setDouble ([ID)V +} + +public final class space/kscience/kmath/nd/OperationsNDKt { + public static final fun roll (Lspace/kscience/kmath/nd/StructureND;II)Lspace/kscience/kmath/nd/StructureND; + public static final fun roll (Lspace/kscience/kmath/nd/StructureND;Lkotlin/Pair;[Lkotlin/Pair;)Lspace/kscience/kmath/nd/StructureND; + public static synthetic fun roll$default (Lspace/kscience/kmath/nd/StructureND;IIILjava/lang/Object;)Lspace/kscience/kmath/nd/StructureND; +} + +public final class space/kscience/kmath/nd/PermutedMutableStructureND : space/kscience/kmath/nd/MutableStructureND { + public synthetic fun (Lspace/kscience/kmath/nd/MutableStructureND;[ILkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Lspace/kscience/kmath/nd/MutableStructureND;[ILkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun get ([I)Ljava/lang/Object; + public final fun getOrigin ()Lspace/kscience/kmath/nd/MutableStructureND; + public final fun getPermutation ()Lkotlin/jvm/functions/Function1; + public fun getShape-IIYLAfE ()[I + public fun set ([ILjava/lang/Object;)V +} + +public final class space/kscience/kmath/nd/PermutedStructureND : space/kscience/kmath/nd/StructureND { + public fun (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function1;)V + public fun get ([I)Ljava/lang/Object; + public final fun getOrigin ()Lspace/kscience/kmath/nd/StructureND; + public final fun getPermutation ()Lkotlin/jvm/functions/Function1; + public fun getShape-IIYLAfE ()[I +} + +public final class space/kscience/kmath/nd/PermutedStructureNDKt { + public static final fun permute (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/PermutedStructureND; + public static final fun permute-_A0By-k (Lspace/kscience/kmath/nd/MutableStructureND;[ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/PermutedMutableStructureND; + public static synthetic fun permute-_A0By-k$default (Lspace/kscience/kmath/nd/MutableStructureND;[ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/PermutedMutableStructureND; +} + +public final class space/kscience/kmath/nd/PrimitiveStructureNDKt { + public static final fun getDouble (Lspace/kscience/kmath/nd/MutableStructureND;[I)D + public static final fun getDouble (Lspace/kscience/kmath/nd/StructureND;[I)D + public static final fun getInt (Lspace/kscience/kmath/nd/StructureND;[I)I +} + public abstract interface class space/kscience/kmath/nd/RingND : space/kscience/kmath/nd/GroupND, space/kscience/kmath/nd/RingOpsND, space/kscience/kmath/nd/WithShape, space/kscience/kmath/operations/Ring { public synthetic fun getOne ()Ljava/lang/Object; public fun getOne ()Lspace/kscience/kmath/nd/StructureND; @@ -1124,26 +1553,84 @@ public abstract interface class space/kscience/kmath/nd/RingOpsND : space/kscien public final class space/kscience/kmath/nd/RingOpsND$Companion { } +public final class space/kscience/kmath/nd/RowStrides : space/kscience/kmath/nd/Strides { + public static final field Companion Lspace/kscience/kmath/nd/RowStrides$Companion; + public synthetic fun ([ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun equals (Ljava/lang/Object;)Z + public fun getLinearSize ()I + public fun getShape-IIYLAfE ()[I + public fun hashCode ()I + public fun index (I)[I +} + +public final class space/kscience/kmath/nd/RowStrides$Companion { +} + public abstract interface class space/kscience/kmath/nd/ShapeIndexer : java/lang/Iterable, kotlin/jvm/internal/markers/KMappedMarker { public abstract fun asSequence ()Lkotlin/sequences/Sequence; public abstract fun equals (Ljava/lang/Object;)Z public abstract fun getLinearSize ()I - public abstract fun getShape ()[I + public abstract fun getShape-IIYLAfE ()[I public abstract fun hashCode ()I public abstract fun index (I)[I public fun iterator ()Ljava/util/Iterator; public abstract fun offset ([I)I } +public final class space/kscience/kmath/nd/ShapeIndicesKt { + public static final fun Strides-dNlrn20 ([I)Lspace/kscience/kmath/nd/Strides; +} + public final class space/kscience/kmath/nd/ShapeMismatchException : java/lang/RuntimeException { - public fun ([I[I)V - public final fun getActual ()[I - public final fun getExpected ()[I + public synthetic fun ([I[ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun getActual-IIYLAfE ()[I + public final fun getExpected-IIYLAfE ()[I +} + +public final class space/kscience/kmath/nd/ShapeND { + public static final synthetic fun box-impl ([I)Lspace/kscience/kmath/nd/ShapeND; + public static fun constructor-impl ([I)[I + public fun equals (Ljava/lang/Object;)Z + public static fun equals-impl ([ILjava/lang/Object;)Z + public static final fun equals-impl0 ([I[I)Z + public static final fun get-impl ([II)I + public static final fun getSize-impl ([I)I + public fun hashCode ()I + public static fun hashCode-impl ([I)I + public fun toString ()Ljava/lang/String; + public static fun toString-impl ([I)Ljava/lang/String; + public final synthetic fun unbox-impl ()[I +} + +public final class space/kscience/kmath/nd/ShapeNDKt { + public static final fun ShapeND (I[I)[I + public static final fun asArray-dNlrn20 ([I)[I + public static final fun asList-dNlrn20 ([I)Ljava/util/List; + public static final fun component1-dNlrn20 ([I)I + public static final fun component2-dNlrn20 ([I)I + public static final fun component3-dNlrn20 ([I)I + public static final fun contentEquals-9Nqdy04 ([I[I)Z + public static final fun contentHashCode-dNlrn20 ([I)I + public static final fun first-dNlrn20 ([I)I + public static final fun first-qL90JFI ([II)[I + public static final fun forEach-qL90JFI ([ILkotlin/jvm/functions/Function1;)V + public static final fun forEachIndexed-qL90JFI ([ILkotlin/jvm/functions/Function2;)V + public static final fun getIndices-dNlrn20 ([I)Lkotlin/ranges/IntRange; + public static final fun getLinearSize-dNlrn20 ([I)I + public static final fun isEmpty-dNlrn20 ([I)Z + public static final fun isNotEmpty-dNlrn20 ([I)Z + public static final fun last-dNlrn20 ([I)I + public static final fun last-qL90JFI ([II)[I + public static final fun plus-9Nqdy04 ([I[I)[I + public static final fun plus-qL90JFI ([I[I)[I + public static final fun slice-qL90JFI ([ILkotlin/ranges/IntRange;)[I + public static final fun toArray-dNlrn20 ([I)[I + public static final fun transposed-bYNkpeI ([III)[I } public final class space/kscience/kmath/nd/ShortRingND : space/kscience/kmath/nd/ShortRingOpsND, space/kscience/kmath/nd/RingND, space/kscience/kmath/operations/NumbersAddOps { - public fun ([I)V - public fun getShape ()[I + public synthetic fun ([ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun getShape-IIYLAfE ()[I public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/nd/BufferND; } @@ -1162,7 +1649,6 @@ public final class space/kscience/kmath/nd/ShortRingOpsND$Companion : space/ksci public abstract class space/kscience/kmath/nd/Strides : space/kscience/kmath/nd/ShapeIndexer { public fun ()V public fun asSequence ()Lkotlin/sequences/Sequence; - public abstract fun getStrides ()[I public fun offset ([I)I } @@ -1191,7 +1677,7 @@ public abstract interface class space/kscience/kmath/nd/Structure2D : space/ksci public fun getColumns ()Ljava/util/List; public abstract fun getRowNum ()I public fun getRows ()Ljava/util/List; - public fun getShape ()[I + public fun getShape-IIYLAfE ()[I } public final class space/kscience/kmath/nd/Structure2D$Companion { @@ -1212,16 +1698,16 @@ public abstract interface class space/kscience/kmath/nd/StructureND : space/ksci public fun getDimension ()I public synthetic fun getFeature (Lkotlin/reflect/KClass;)Ljava/lang/Object; public fun getFeature (Lkotlin/reflect/KClass;)Lspace/kscience/kmath/nd/StructureFeature; - public abstract fun getShape ()[I + public abstract fun getShape-IIYLAfE ()[I } public final class space/kscience/kmath/nd/StructureND$Companion { public final fun auto (Lkotlin/reflect/KClass;Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/BufferND; public final fun auto (Lkotlin/reflect/KClass;[ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/BufferND; - public final fun buffered (Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/BufferND; - public final fun buffered ([ILkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/BufferND; - public static synthetic fun buffered$default (Lspace/kscience/kmath/nd/StructureND$Companion;Lspace/kscience/kmath/nd/Strides;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/BufferND; - public static synthetic fun buffered$default (Lspace/kscience/kmath/nd/StructureND$Companion;[ILkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/BufferND; + public final fun buffered (Lspace/kscience/kmath/nd/Strides;Lspace/kscience/kmath/structures/BufferFactory;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/BufferND; + public static synthetic fun buffered$default (Lspace/kscience/kmath/nd/StructureND$Companion;Lspace/kscience/kmath/nd/Strides;Lspace/kscience/kmath/structures/BufferFactory;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/BufferND; + public final fun buffered-bYNkpeI ([ILspace/kscience/kmath/structures/BufferFactory;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/BufferND; + public static synthetic fun buffered-bYNkpeI$default (Lspace/kscience/kmath/nd/StructureND$Companion;[ILspace/kscience/kmath/structures/BufferFactory;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/kmath/nd/BufferND; public final fun contentEquals (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Z public final fun contentEquals (Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;D)Z public static synthetic fun contentEquals$default (Lspace/kscience/kmath/nd/StructureND$Companion;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;DILjava/lang/Object;)Z @@ -1233,13 +1719,38 @@ public final class space/kscience/kmath/nd/StructureNDKt { public static final fun contentEquals (Lspace/kscience/kmath/linear/LinearSpace;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Comparable;)Z public static final fun contentEquals (Lspace/kscience/kmath/nd/AlgebraND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;)Z public static final fun contentEquals (Lspace/kscience/kmath/nd/GroupOpsND;Lspace/kscience/kmath/nd/StructureND;Lspace/kscience/kmath/nd/StructureND;Ljava/lang/Comparable;)Z + public static final fun get (Lspace/kscience/kmath/nd/StructureND;[I)D + public static final fun get (Lspace/kscience/kmath/nd/StructureND;[I)I public static final fun get (Lspace/kscience/kmath/nd/StructureND;[I)Ljava/lang/Object; - public static final fun mapInPlace (Lspace/kscience/kmath/nd/MutableStructureND;Lkotlin/jvm/functions/Function2;)V + public static final fun set (Lspace/kscience/kmath/nd/MutableStructureND;[ILjava/lang/Object;)V +} + +public abstract interface class space/kscience/kmath/nd/StructureNDOfDouble : space/kscience/kmath/nd/StructureND { + public abstract fun getDouble ([I)D +} + +public abstract interface class space/kscience/kmath/nd/StructureNDOfInt : space/kscience/kmath/nd/StructureND { + public abstract fun getInt ([I)I +} + +public final class space/kscience/kmath/nd/VirtualDoubleStructureND : space/kscience/kmath/nd/VirtualStructureND { + public synthetic fun ([ILkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V +} + +public final class space/kscience/kmath/nd/VirtualIntStructureND : space/kscience/kmath/nd/VirtualStructureND { + public synthetic fun ([ILkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V +} + +public class space/kscience/kmath/nd/VirtualStructureND : space/kscience/kmath/nd/StructureND { + public synthetic fun ([ILkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun get ([I)Ljava/lang/Object; + public final fun getProducer ()Lkotlin/jvm/functions/Function1; + public fun getShape-IIYLAfE ()[I } public abstract interface class space/kscience/kmath/nd/WithShape { public fun getIndices ()Lspace/kscience/kmath/nd/ShapeIndexer; - public abstract fun getShape ()[I + public abstract fun getShape-IIYLAfE ()[I } public abstract interface class space/kscience/kmath/operations/Algebra { @@ -1247,6 +1758,8 @@ public abstract interface class space/kscience/kmath/operations/Algebra { public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public fun export (Ljava/lang/Object;)Ljava/lang/Object; + public fun getBufferFactory ()Lspace/kscience/kmath/structures/MutableBufferFactory; public fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } @@ -1255,12 +1768,15 @@ public final class space/kscience/kmath/operations/AlgebraExtensionsKt { public static final fun abs (Lspace/kscience/kmath/operations/Group;Ljava/lang/Comparable;)Ljava/lang/Comparable; public static final fun average (Lspace/kscience/kmath/operations/Group;Ljava/lang/Iterable;)Ljava/lang/Object; public static final fun average (Lspace/kscience/kmath/operations/Group;Lkotlin/sequences/Sequence;)Ljava/lang/Object; + public static final fun average (Lspace/kscience/kmath/operations/Group;Lspace/kscience/kmath/structures/Buffer;)Ljava/lang/Object; public static final fun averageWith (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Group;)Ljava/lang/Object; public static final fun averageWith (Lkotlin/sequences/Sequence;Lspace/kscience/kmath/operations/Group;)Ljava/lang/Object; public static final fun sum (Lspace/kscience/kmath/operations/Group;Ljava/lang/Iterable;)Ljava/lang/Object; public static final fun sum (Lspace/kscience/kmath/operations/Group;Lkotlin/sequences/Sequence;)Ljava/lang/Object; + public static final fun sum (Lspace/kscience/kmath/operations/Group;Lspace/kscience/kmath/structures/Buffer;)Ljava/lang/Object; public static final fun sumWith (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Group;)Ljava/lang/Object; public static final fun sumWith (Lkotlin/sequences/Sequence;Lspace/kscience/kmath/operations/Group;)Ljava/lang/Object; + public static final fun sumWithGroupOf (Ljava/lang/Iterable;Lspace/kscience/kmath/operations/Group;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; } public final class space/kscience/kmath/operations/AlgebraKt { @@ -1327,12 +1843,10 @@ public final class space/kscience/kmath/operations/BigIntField : space/kscience/ public final class space/kscience/kmath/operations/BigIntKt { public static final fun abs (Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigInt; - public static final fun bigInt (Lspace/kscience/kmath/structures/Buffer$Companion;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; - public static final fun bigInt (Lspace/kscience/kmath/structures/MutableBuffer$Companion;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/MutableBuffer; public static final fun buffer (Lspace/kscience/kmath/operations/BigInt$Companion;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; public static final fun getAlgebra (Lspace/kscience/kmath/operations/BigInt;)Lspace/kscience/kmath/operations/BigIntField; public static final fun getNd (Lspace/kscience/kmath/operations/BigIntField;)Lspace/kscience/kmath/nd/BufferedRingOpsND; - public static final fun mutableBuffer (Lspace/kscience/kmath/operations/BigInt;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; + public static final fun mutableBuffer (Lspace/kscience/kmath/operations/BigInt$Companion;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; public static final fun parseBigInteger (Ljava/lang/String;)Lspace/kscience/kmath/operations/BigInt; public static final fun toBigInt (I)Lspace/kscience/kmath/operations/BigInt; public static final fun toBigInt (J)Lspace/kscience/kmath/operations/BigInt; @@ -1341,11 +1855,25 @@ public final class space/kscience/kmath/operations/BigIntKt { public static final fun toBigInt-WZ4Q5Ns (I)Lspace/kscience/kmath/operations/BigInt; } +public final class space/kscience/kmath/operations/BooleanAlgebra : space/kscience/kmath/operations/LogicAlgebra { + public static final field INSTANCE Lspace/kscience/kmath/operations/BooleanAlgebra; + public synthetic fun and (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun and (ZZ)Ljava/lang/Boolean; + public fun const (Z)Ljava/lang/Boolean; + public synthetic fun const (Z)Ljava/lang/Object; + public synthetic fun not (Ljava/lang/Object;)Ljava/lang/Object; + public fun not (Z)Ljava/lang/Boolean; + public synthetic fun or (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun or (ZZ)Ljava/lang/Boolean; + public synthetic fun xor (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun xor (ZZ)Ljava/lang/Boolean; +} + public abstract interface class space/kscience/kmath/operations/BufferAlgebra : space/kscience/kmath/operations/Algebra { public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun buffer (I[Ljava/lang/Object;)Lspace/kscience/kmath/structures/Buffer; - public abstract fun getBufferFactory ()Lkotlin/jvm/functions/Function2; public abstract fun getElementAlgebra ()Lspace/kscience/kmath/operations/Algebra; + public fun getElementBufferFactory ()Lspace/kscience/kmath/structures/BufferFactory; public fun map (Lspace/kscience/kmath/structures/Buffer;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; public fun mapIndexed (Lspace/kscience/kmath/structures/Buffer;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/structures/Buffer; public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; @@ -1362,11 +1890,11 @@ public final class space/kscience/kmath/operations/BufferAlgebraKt { public static final fun buffer (Lspace/kscience/kmath/operations/BufferAlgebra;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; public static final fun buffer (Lspace/kscience/kmath/operations/BufferAlgebra;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; public static final fun buffer (Lspace/kscience/kmath/operations/BufferField;[Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; - public static final fun bufferAlgebra (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/operations/BufferFieldOps; public static final fun cos (Lspace/kscience/kmath/operations/BufferAlgebra;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public static final fun cosh (Lspace/kscience/kmath/operations/BufferAlgebra;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public static final fun exp (Lspace/kscience/kmath/operations/BufferAlgebra;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; - public static final fun getBufferAlgebra (Lspace/kscience/kmath/operations/DoubleField;)Lspace/kscience/kmath/operations/BufferFieldOps; + public static final fun getBufferAlgebra (Lspace/kscience/kmath/operations/Field;)Lspace/kscience/kmath/operations/BufferFieldOps; + public static final fun getBufferAlgebra (Lspace/kscience/kmath/operations/IntRing;)Lspace/kscience/kmath/operations/BufferRingOps; public static final fun getBufferAlgebra (Lspace/kscience/kmath/operations/ShortRing;)Lspace/kscience/kmath/operations/BufferRingOps; public static final fun ln (Lspace/kscience/kmath/operations/BufferAlgebra;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public static final fun pow (Lspace/kscience/kmath/operations/BufferAlgebra;Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; @@ -1377,8 +1905,21 @@ public final class space/kscience/kmath/operations/BufferAlgebraKt { public static final fun withSize (Lspace/kscience/kmath/operations/BufferFieldOps;I)Lspace/kscience/kmath/operations/BufferField; } +public final class space/kscience/kmath/operations/BufferExtensionsKt { + public static final fun asIterable (Lspace/kscience/kmath/structures/Buffer;)Ljava/lang/Iterable; + public static final fun asSequence (Lspace/kscience/kmath/structures/Buffer;)Lkotlin/sequences/Sequence; + public static final fun combineToBuffer (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/BufferFactory;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; + public static final fun fold (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; + public static final fun foldIndexed (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;Lkotlin/jvm/functions/Function3;)Ljava/lang/Object; + public static final fun mapIndexedToBuffer (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/BufferFactory;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; + public static final fun mapToBuffer (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/BufferFactory;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; + public static final fun reduce (Lspace/kscience/kmath/structures/Buffer;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; + public static final fun toList (Lspace/kscience/kmath/structures/Buffer;)Ljava/util/List; + public static final fun toMutableList (Lspace/kscience/kmath/structures/Buffer;)Ljava/util/List; +} + public final class space/kscience/kmath/operations/BufferField : space/kscience/kmath/operations/BufferFieldOps, space/kscience/kmath/operations/Field, space/kscience/kmath/operations/WithSize { - public fun (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function2;I)V + public fun (Lspace/kscience/kmath/operations/Field;I)V public synthetic fun getOne ()Ljava/lang/Object; public fun getOne ()Lspace/kscience/kmath/structures/Buffer; public fun getSize ()I @@ -1387,7 +1928,7 @@ public final class space/kscience/kmath/operations/BufferField : space/kscience/ } public class space/kscience/kmath/operations/BufferFieldOps : space/kscience/kmath/operations/BufferRingOps, space/kscience/kmath/operations/BufferAlgebra, space/kscience/kmath/operations/FieldOps, space/kscience/kmath/operations/ScaleOperations { - public fun (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function2;)V + public fun (Lspace/kscience/kmath/operations/Field;)V public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun divide (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; @@ -1397,20 +1938,11 @@ public class space/kscience/kmath/operations/BufferFieldOps : space/kscience/kma public fun unaryMinus (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; } -public final class space/kscience/kmath/operations/BufferOperationKt { - public static final fun asIterable (Lspace/kscience/kmath/structures/Buffer;)Ljava/lang/Iterable; - public static final fun asSequence (Lspace/kscience/kmath/structures/Buffer;)Lkotlin/sequences/Sequence; - public static final fun fold (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public static final fun map (Lspace/kscience/kmath/structures/Buffer;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; - public static final fun toList (Lspace/kscience/kmath/structures/Buffer;)Ljava/util/List; -} - public class space/kscience/kmath/operations/BufferRingOps : space/kscience/kmath/operations/BufferAlgebra, space/kscience/kmath/operations/RingOps { - public fun (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)V + public fun (Lspace/kscience/kmath/operations/Ring;)V public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun add (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public fun getBufferFactory ()Lkotlin/jvm/functions/Function2; public synthetic fun getElementAlgebra ()Lspace/kscience/kmath/operations/Algebra; public fun getElementAlgebra ()Lspace/kscience/kmath/operations/Ring; public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @@ -1420,10 +1952,15 @@ public class space/kscience/kmath/operations/BufferRingOps : space/kscience/kmat public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } +public abstract interface class space/kscience/kmath/operations/BufferTransform { + public abstract fun transform (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; +} + public final class space/kscience/kmath/operations/ByteRing : space/kscience/kmath/operations/Norm, space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/Ring { public static final field INSTANCE Lspace/kscience/kmath/operations/ByteRing; public fun add (BB)Ljava/lang/Byte; public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun getBufferFactory ()Lspace/kscience/kmath/structures/MutableBufferFactory; public fun getOne ()Ljava/lang/Byte; public synthetic fun getOne ()Ljava/lang/Object; public fun getZero ()Ljava/lang/Byte; @@ -1460,6 +1997,7 @@ public final class space/kscience/kmath/operations/DoubleBufferField : space/ksc public synthetic fun getZero ()Ljava/lang/Object; public fun getZero ()Lspace/kscience/kmath/structures/Buffer; public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public synthetic fun power (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; public fun power-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)[D public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; public fun sinh-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D @@ -1494,13 +2032,16 @@ public abstract class space/kscience/kmath/operations/DoubleBufferOps : space/ks public fun divide-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; public fun exp-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D - public fun getBufferFactory ()Lkotlin/jvm/functions/Function2; public synthetic fun getElementAlgebra ()Lspace/kscience/kmath/operations/Algebra; public fun getElementAlgebra ()Lspace/kscience/kmath/operations/DoubleField; + public synthetic fun getElementBufferFactory ()Lspace/kscience/kmath/structures/BufferFactory; + public fun getElementBufferFactory ()Lspace/kscience/kmath/structures/MutableBufferFactory; public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; public fun ln-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun map (Lspace/kscience/kmath/structures/Buffer;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; - public fun map-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Lkotlin/jvm/functions/Function2;)[D + public final fun map-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Lkotlin/jvm/functions/Function2;)[D + public synthetic fun mapIndexed (Lspace/kscience/kmath/structures/Buffer;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/structures/Buffer; + public final fun mapIndexed-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Lkotlin/jvm/functions/Function3;)[D public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun minus-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @@ -1509,6 +2050,8 @@ public abstract class space/kscience/kmath/operations/DoubleBufferOps : space/ks public fun norm (Lspace/kscience/kmath/structures/Buffer;)Ljava/lang/Double; public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun plus-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D + public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun power (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Number;)Lspace/kscience/kmath/structures/Buffer; public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; public fun scale-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;D)[D public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; @@ -1522,10 +2065,21 @@ public abstract class space/kscience/kmath/operations/DoubleBufferOps : space/ks public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryMinus-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; + public synthetic fun zip (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/structures/Buffer; + public final fun zip-XquIszc (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;Lkotlin/jvm/functions/Function3;)[D } public final class space/kscience/kmath/operations/DoubleBufferOps$Companion : space/kscience/kmath/operations/DoubleBufferOps { - public final fun mapInline-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Lkotlin/jvm/functions/Function1;)[D +} + +public final class space/kscience/kmath/operations/DoubleBufferOpsKt { + public static final fun average (Lspace/kscience/kmath/operations/DoubleBufferOps;Lspace/kscience/kmath/structures/Buffer;)D + public static final fun averageOf (Lspace/kscience/kmath/operations/DoubleBufferOps;Lspace/kscience/kmath/structures/Buffer;Lkotlin/jvm/functions/Function1;)D + public static final fun covariance (Lspace/kscience/kmath/operations/DoubleBufferOps;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)D + public static final fun dispersion (Lspace/kscience/kmath/operations/DoubleBufferOps;Lspace/kscience/kmath/structures/Buffer;)D + public static final fun std (Lspace/kscience/kmath/operations/DoubleBufferOps;Lspace/kscience/kmath/structures/Buffer;)D + public static final fun sum (Lspace/kscience/kmath/operations/DoubleBufferOps;Lspace/kscience/kmath/structures/Buffer;)D + public static final fun sumOf (Lspace/kscience/kmath/operations/DoubleBufferOps;Lspace/kscience/kmath/structures/Buffer;Lkotlin/jvm/functions/Function1;)D } public final class space/kscience/kmath/operations/DoubleField : space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/Norm, space/kscience/kmath/operations/ScaleOperations { @@ -1555,6 +2109,7 @@ public final class space/kscience/kmath/operations/DoubleField : space/kscience/ public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun exp (D)Ljava/lang/Double; public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; + public fun getBufferFactory ()Lspace/kscience/kmath/structures/MutableBufferFactory; public fun getOne ()Ljava/lang/Double; public synthetic fun getOne ()Ljava/lang/Object; public fun getZero ()Ljava/lang/Double; @@ -1628,7 +2183,7 @@ public final class space/kscience/kmath/operations/ExponentialOperations$Compani public static final field TANH_OPERATION Ljava/lang/String; } -public abstract interface class space/kscience/kmath/operations/ExtendedField : space/kscience/kmath/operations/ExtendedFieldOps, space/kscience/kmath/operations/Field, space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/PowerOperations { +public abstract interface class space/kscience/kmath/operations/ExtendedField : space/kscience/kmath/operations/ExtendedFieldOps, space/kscience/kmath/operations/Field, space/kscience/kmath/operations/NumericAlgebra { public fun acosh (Ljava/lang/Object;)Ljava/lang/Object; public fun asinh (Ljava/lang/Object;)Ljava/lang/Object; public fun atanh (Ljava/lang/Object;)Ljava/lang/Object; @@ -1639,7 +2194,7 @@ public abstract interface class space/kscience/kmath/operations/ExtendedField : public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } -public abstract interface class space/kscience/kmath/operations/ExtendedFieldOps : space/kscience/kmath/operations/ExponentialOperations, space/kscience/kmath/operations/FieldOps, space/kscience/kmath/operations/ScaleOperations, space/kscience/kmath/operations/TrigonometricOperations { +public abstract interface class space/kscience/kmath/operations/ExtendedFieldOps : space/kscience/kmath/operations/ExponentialOperations, space/kscience/kmath/operations/FieldOps, space/kscience/kmath/operations/PowerOperations, space/kscience/kmath/operations/ScaleOperations, space/kscience/kmath/operations/TrigonometricOperations { public fun tan (Ljava/lang/Object;)Ljava/lang/Object; public fun tanh (Ljava/lang/Object;)Ljava/lang/Object; public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; @@ -1693,6 +2248,7 @@ public final class space/kscience/kmath/operations/FloatField : space/kscience/k public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun exp (F)Ljava/lang/Float; public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; + public fun getBufferFactory ()Lspace/kscience/kmath/structures/MutableBufferFactory; public fun getOne ()Ljava/lang/Float; public synthetic fun getOne ()Ljava/lang/Object; public fun getZero ()Ljava/lang/Float; @@ -1755,6 +2311,7 @@ public final class space/kscience/kmath/operations/IntRing : space/kscience/kmat public static final field INSTANCE Lspace/kscience/kmath/operations/IntRing; public fun add (II)Ljava/lang/Integer; public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun getBufferFactory ()Lspace/kscience/kmath/structures/MutableBufferFactory; public fun getOne ()Ljava/lang/Integer; public synthetic fun getOne ()Ljava/lang/Object; public fun getZero ()Ljava/lang/Integer; @@ -1833,7 +2390,18 @@ public final class space/kscience/kmath/operations/JBigIntegerField : space/ksci public fun unaryMinus (Ljava/math/BigInteger;)Ljava/math/BigInteger; } -public abstract interface annotation class space/kscience/kmath/operations/KMathContext : java/lang/annotation/Annotation { +public abstract interface class space/kscience/kmath/operations/LogicAlgebra : space/kscience/kmath/operations/Algebra { + public static final field Companion Lspace/kscience/kmath/operations/LogicAlgebra$Companion; + public abstract fun and (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; + public fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; + public abstract fun const (Z)Ljava/lang/Object; + public abstract fun not (Ljava/lang/Object;)Ljava/lang/Object; + public abstract fun or (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; + public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; + public abstract fun xor (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; } public final class space/kscience/kmath/operations/LogicAlgebra$Companion { @@ -1845,6 +2413,7 @@ public final class space/kscience/kmath/operations/LongRing : space/kscience/kma public static final field INSTANCE Lspace/kscience/kmath/operations/LongRing; public fun add (JJ)Ljava/lang/Long; public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun getBufferFactory ()Lspace/kscience/kmath/structures/MutableBufferFactory; public fun getOne ()Ljava/lang/Long; public synthetic fun getOne ()Ljava/lang/Object; public fun getZero ()Ljava/lang/Long; @@ -1869,6 +2438,13 @@ public abstract interface class space/kscience/kmath/operations/Norm { public abstract fun norm (Ljava/lang/Object;)Ljava/lang/Object; } +public abstract interface class space/kscience/kmath/operations/NumbersAddOps : space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/RingOps { + public fun minus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun minus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; + public fun plus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; + public fun plus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; +} + public final class space/kscience/kmath/operations/NumbersKt { public static final fun getAlgebra (Lkotlin/jvm/internal/ByteCompanionObject;)Lspace/kscience/kmath/operations/ByteRing; public static final fun getAlgebra (Lkotlin/jvm/internal/DoubleCompanionObject;)Lspace/kscience/kmath/operations/DoubleField; @@ -1938,6 +2514,7 @@ public final class space/kscience/kmath/operations/ShortRing : space/kscience/km public static final field INSTANCE Lspace/kscience/kmath/operations/ShortRing; public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun add (SS)Ljava/lang/Short; + public fun getBufferFactory ()Lspace/kscience/kmath/structures/MutableBufferFactory; public synthetic fun getOne ()Ljava/lang/Object; public fun getOne ()Ljava/lang/Short; public synthetic fun getZero ()Ljava/lang/Object; @@ -2001,11 +2578,11 @@ public final class space/kscience/kmath/structures/ArrayBufferKt { public static final fun asBuffer ([Ljava/lang/Object;)Lspace/kscience/kmath/structures/ArrayBuffer; } -public abstract interface class space/kscience/kmath/structures/Buffer { +public abstract interface class space/kscience/kmath/structures/Buffer : space/kscience/kmath/operations/WithSize { public static final field Companion Lspace/kscience/kmath/structures/Buffer$Companion; public abstract fun get (I)Ljava/lang/Object; public abstract fun getSize ()I - public abstract fun iterator ()Ljava/util/Iterator; + public fun iterator ()Ljava/util/Iterator; public abstract fun toString ()Ljava/lang/String; } @@ -2016,14 +2593,100 @@ public final class space/kscience/kmath/structures/Buffer$Companion { public final fun toString (Lspace/kscience/kmath/structures/Buffer;)Ljava/lang/String; } +public final class space/kscience/kmath/structures/BufferExpanded : space/kscience/kmath/structures/BufferView { + public fun (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;II)V + public synthetic fun (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;IIILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun get (I)Ljava/lang/Object; + public final fun getOffset ()I + public fun getOrigin ()Lspace/kscience/kmath/structures/Buffer; + public fun getSize ()I + public fun originIndex (I)I + public fun toString ()Ljava/lang/String; +} + +public abstract interface class space/kscience/kmath/structures/BufferFactory { + public static final field Companion Lspace/kscience/kmath/structures/BufferFactory$Companion; + public abstract fun invoke (ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; +} + +public final class space/kscience/kmath/structures/BufferFactory$Companion { + public final fun boxing ()Lspace/kscience/kmath/structures/BufferFactory; +} + public final class space/kscience/kmath/structures/BufferKt { public static final fun asReadOnly (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public static final fun first (Lspace/kscience/kmath/structures/Buffer;)Ljava/lang/Object; + public static final fun get-Qn1smSk (Lspace/kscience/kmath/structures/Buffer;I)Ljava/lang/Object; public static final fun getIndices (Lspace/kscience/kmath/structures/Buffer;)Lkotlin/ranges/IntRange; + public static final fun getOrNull (Lspace/kscience/kmath/structures/Buffer;I)Ljava/lang/Object; public static final fun last (Lspace/kscience/kmath/structures/Buffer;)Ljava/lang/Object; } -public final class space/kscience/kmath/structures/DoubleBuffer : space/kscience/kmath/structures/MutableBuffer { +public final class space/kscience/kmath/structures/BufferPrimitiveAccessKt { + public static final fun getDouble (Lspace/kscience/kmath/structures/Buffer;I)D + public static final fun getInt (Lspace/kscience/kmath/structures/Buffer;I)I +} + +public final class space/kscience/kmath/structures/BufferSlice : space/kscience/kmath/structures/BufferView { + public fun (Lspace/kscience/kmath/structures/Buffer;II)V + public synthetic fun (Lspace/kscience/kmath/structures/Buffer;IIILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun get (I)Ljava/lang/Object; + public final fun getOffset ()I + public fun getOrigin ()Lspace/kscience/kmath/structures/Buffer; + public fun getSize ()I + public fun iterator ()Ljava/util/Iterator; + public fun originIndex (I)I + public fun toString ()Ljava/lang/String; +} + +public abstract interface class space/kscience/kmath/structures/BufferView : space/kscience/kmath/structures/Buffer { + public fun get (I)Ljava/lang/Object; + public abstract fun getOrigin ()Lspace/kscience/kmath/structures/Buffer; + public abstract fun originIndex (I)I +} + +public final class space/kscience/kmath/structures/BufferViewKt { + public static final fun expand (Lspace/kscience/kmath/structures/Buffer;Lkotlin/ranges/IntRange;Ljava/lang/Object;)Lspace/kscience/kmath/structures/BufferView; + public static final fun permute (Lspace/kscience/kmath/structures/Buffer;[I)Lspace/kscience/kmath/structures/PermutedBuffer; + public static final fun permute (Lspace/kscience/kmath/structures/MutableBuffer;[I)Lspace/kscience/kmath/structures/PermutedMutableBuffer; + public static final fun slice (Lspace/kscience/kmath/structures/Buffer;Lkotlin/ranges/IntRange;)Lspace/kscience/kmath/structures/BufferView; +} + +public final class space/kscience/kmath/structures/ByteBuffer : space/kscience/kmath/structures/MutableBuffer { + public static final synthetic fun box-impl ([B)Lspace/kscience/kmath/structures/ByteBuffer; + public static fun constructor-impl ([B)[B + public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; + public static fun copy-impl ([B)Lspace/kscience/kmath/structures/MutableBuffer; + public fun equals (Ljava/lang/Object;)Z + public static fun equals-impl ([BLjava/lang/Object;)Z + public static final fun equals-impl0 ([B[B)Z + public fun get (I)Ljava/lang/Byte; + public synthetic fun get (I)Ljava/lang/Object; + public static fun get-impl ([BI)Ljava/lang/Byte; + public final fun getArray ()[B + public fun getSize ()I + public static fun getSize-impl ([B)I + public fun hashCode ()I + public static fun hashCode-impl ([B)I + public synthetic fun iterator ()Ljava/util/Iterator; + public fun iterator ()Lkotlin/collections/ByteIterator; + public static fun iterator-impl ([B)Lkotlin/collections/ByteIterator; + public fun set (IB)V + public synthetic fun set (ILjava/lang/Object;)V + public static fun set-impl ([BIB)V + public fun toString ()Ljava/lang/String; + public static fun toString-impl ([B)Ljava/lang/String; + public final synthetic fun unbox-impl ()[B +} + +public final class space/kscience/kmath/structures/ByteBufferKt { + public static final fun ByteBuffer (ILkotlin/jvm/functions/Function1;)[B + public static final fun ByteBuffer ([B)[B + public static final fun asBuffer ([B)[B + public static final fun toByteArray (Lspace/kscience/kmath/structures/Buffer;)[B +} + +public final class space/kscience/kmath/structures/DoubleBuffer : space/kscience/kmath/structures/PrimitiveBuffer { public static final field Companion Lspace/kscience/kmath/structures/DoubleBuffer$Companion; public static final synthetic fun box-impl ([D)Lspace/kscience/kmath/structures/DoubleBuffer; public static fun constructor-impl ([D)[D @@ -2060,8 +2723,14 @@ public final class space/kscience/kmath/structures/DoubleBufferKt { public static final fun DoubleBuffer (ILkotlin/jvm/functions/Function1;)[D public static final fun DoubleBuffer ([D)[D public static final fun asBuffer ([D)[D - public static final fun contentEquals-2c9zdjM ([D[D)Z public static final fun toDoubleArray (Lspace/kscience/kmath/structures/Buffer;)[D + public static final fun toDoubleBuffer (Lspace/kscience/kmath/structures/Buffer;)[D +} + +public abstract interface class space/kscience/kmath/structures/DoubleBufferTransform : space/kscience/kmath/operations/BufferTransform { + public synthetic fun transform (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; + public abstract fun transform-7Zdoou4 ([D)[D + public fun transform-Udx-57Q (Lspace/kscience/kmath/structures/Buffer;)[D } public abstract interface class space/kscience/kmath/structures/FlaggedBuffer : space/kscience/kmath/structures/Buffer { @@ -2087,7 +2756,7 @@ public final class space/kscience/kmath/structures/FlaggedDoubleBuffer : space/k public fun toString ()Ljava/lang/String; } -public final class space/kscience/kmath/structures/FloatBuffer : space/kscience/kmath/structures/MutableBuffer { +public final class space/kscience/kmath/structures/FloatBuffer : space/kscience/kmath/structures/PrimitiveBuffer { public static final synthetic fun box-impl ([F)Lspace/kscience/kmath/structures/FloatBuffer; public static fun constructor-impl ([F)[F public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; @@ -2121,11 +2790,12 @@ public final class space/kscience/kmath/structures/FloatBufferKt { public static final fun toFloatArray (Lspace/kscience/kmath/structures/Buffer;)[F } -public final class space/kscience/kmath/structures/IntBuffer : space/kscience/kmath/structures/MutableBuffer { +public final class space/kscience/kmath/structures/IntBuffer : space/kscience/kmath/structures/PrimitiveBuffer { public static final synthetic fun box-impl ([I)Lspace/kscience/kmath/structures/IntBuffer; public static fun constructor-impl ([I)[I - public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; - public static fun copy-impl ([I)Lspace/kscience/kmath/structures/MutableBuffer; + public synthetic fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; + public fun copy-ir4F4A8 ()[I + public static fun copy-ir4F4A8 ([I)[I public fun equals (Ljava/lang/Object;)Z public static fun equals-impl ([ILjava/lang/Object;)Z public static final fun equals-impl0 ([I[I)Z @@ -2170,7 +2840,7 @@ public final class space/kscience/kmath/structures/ListBufferKt { public static final fun asMutableBuffer (Ljava/util/List;)Ljava/util/List; } -public final class space/kscience/kmath/structures/LongBuffer : space/kscience/kmath/structures/MutableBuffer { +public final class space/kscience/kmath/structures/LongBuffer : space/kscience/kmath/structures/PrimitiveBuffer { public static final synthetic fun box-impl ([J)Lspace/kscience/kmath/structures/LongBuffer; public static fun constructor-impl ([J)[J public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; @@ -2236,6 +2906,15 @@ public final class space/kscience/kmath/structures/MutableBuffer$Companion { public final fun short-1yRgbGw (ILkotlin/jvm/functions/Function1;)[S } +public abstract interface class space/kscience/kmath/structures/MutableBufferFactory : space/kscience/kmath/structures/BufferFactory { + public static final field Companion Lspace/kscience/kmath/structures/MutableBufferFactory$Companion; + public abstract fun invoke (ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/MutableBuffer; +} + +public final class space/kscience/kmath/structures/MutableBufferFactory$Companion { + public final fun boxing ()Lspace/kscience/kmath/structures/MutableBufferFactory; +} + public final class space/kscience/kmath/structures/MutableListBuffer : space/kscience/kmath/structures/MutableBuffer { public static final synthetic fun box-impl (Ljava/util/List;)Lspace/kscience/kmath/structures/MutableListBuffer; public static fun constructor-impl (ILkotlin/jvm/functions/Function1;)Ljava/util/List; @@ -2273,6 +2952,32 @@ public final class space/kscience/kmath/structures/MutableMemoryBuffer$Companion public final fun create (Lspace/kscience/kmath/memory/MemorySpec;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/MutableMemoryBuffer; } +public final class space/kscience/kmath/structures/PermutedBuffer : space/kscience/kmath/structures/BufferView { + public fun (Lspace/kscience/kmath/structures/Buffer;[I)V + public fun get (I)Ljava/lang/Object; + public fun getOrigin ()Lspace/kscience/kmath/structures/Buffer; + public fun getSize ()I + public fun iterator ()Ljava/util/Iterator; + public fun originIndex (I)I + public fun toString ()Ljava/lang/String; +} + +public final class space/kscience/kmath/structures/PermutedMutableBuffer : space/kscience/kmath/structures/BufferView, space/kscience/kmath/structures/MutableBuffer { + public fun (Lspace/kscience/kmath/structures/MutableBuffer;[I)V + public fun copy ()Lspace/kscience/kmath/structures/MutableBuffer; + public fun get (I)Ljava/lang/Object; + public synthetic fun getOrigin ()Lspace/kscience/kmath/structures/Buffer; + public fun getOrigin ()Lspace/kscience/kmath/structures/MutableBuffer; + public fun getSize ()I + public fun iterator ()Ljava/util/Iterator; + public fun originIndex (I)I + public fun set (ILjava/lang/Object;)V + public fun toString ()Ljava/lang/String; +} + +public abstract interface class space/kscience/kmath/structures/PrimitiveBuffer : space/kscience/kmath/structures/MutableBuffer { +} + public final class space/kscience/kmath/structures/ReadOnlyBuffer : space/kscience/kmath/structures/Buffer { public static final synthetic fun box-impl (Lspace/kscience/kmath/structures/MutableBuffer;)Lspace/kscience/kmath/structures/ReadOnlyBuffer; public static fun constructor-impl (Lspace/kscience/kmath/structures/MutableBuffer;)Lspace/kscience/kmath/structures/MutableBuffer; 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 791d7d16f..353892105 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,6 @@ import space.kscience.kmath.UnstableKMathAPI /** * Non-boxing access to primitive [Double] */ - @UnstableKMathAPI public fun Buffer.getDouble(index: Int): Double = if (this is BufferView) { val originIndex = originIndex(index) diff --git a/kmath-memory/api/kmath-memory.api b/kmath-memory/api/kmath-memory.api index 9c9641461..cebb04af2 100644 --- a/kmath-memory/api/kmath-memory.api +++ b/kmath-memory/api/kmath-memory.api @@ -1,3 +1,14 @@ +public abstract interface annotation class space/kscience/kmath/PerformancePitfall : java/lang/annotation/Annotation { + public abstract fun message ()Ljava/lang/String; +} + +public abstract interface annotation class space/kscience/kmath/UnsafeKMathAPI : java/lang/annotation/Annotation { + public abstract fun message ()Ljava/lang/String; +} + +public abstract interface annotation class space/kscience/kmath/UnstableKMathAPI : java/lang/annotation/Annotation { +} + public final class space/kscience/kmath/memory/ByteBufferMemory : space/kscience/kmath/memory/Memory { public fun (Ljava/nio/ByteBuffer;II)V public synthetic fun (Ljava/nio/ByteBuffer;IIILkotlin/jvm/internal/DefaultConstructorMarker;)V @@ -36,7 +47,8 @@ public final class space/kscience/kmath/memory/MemoryKt { public static final fun write (Lspace/kscience/kmath/memory/Memory;Lkotlin/jvm/functions/Function1;)V } -public abstract interface class space/kscience/kmath/memory/MemoryReader { +public abstract interface class space/kscience/kmath/memory/MemoryReader : java/lang/AutoCloseable { + public abstract fun close ()V public abstract fun getMemory ()Lspace/kscience/kmath/memory/Memory; public abstract fun readByte (I)B public abstract fun readDouble (I)D @@ -44,7 +56,6 @@ public abstract interface class space/kscience/kmath/memory/MemoryReader { public abstract fun readInt (I)I public abstract fun readLong (I)J public abstract fun readShort (I)S - public abstract fun release ()V } public abstract interface class space/kscience/kmath/memory/MemorySpec { @@ -59,9 +70,9 @@ public final class space/kscience/kmath/memory/MemorySpecKt { public static final fun writeArray (Lspace/kscience/kmath/memory/MemoryWriter;Lspace/kscience/kmath/memory/MemorySpec;I[Ljava/lang/Object;)V } -public abstract interface class space/kscience/kmath/memory/MemoryWriter { +public abstract interface class space/kscience/kmath/memory/MemoryWriter : java/lang/AutoCloseable { + public abstract fun close ()V public abstract fun getMemory ()Lspace/kscience/kmath/memory/Memory; - public abstract fun release ()V public abstract fun writeByte (IB)V public abstract fun writeDouble (ID)V public abstract fun writeFloat (IF)V diff --git a/kmath-viktor/api/kmath-viktor.api b/kmath-viktor/api/kmath-viktor.api index 3bb7c3b21..39ae1f84c 100644 --- a/kmath-viktor/api/kmath-viktor.api +++ b/kmath-viktor/api/kmath-viktor.api @@ -29,7 +29,7 @@ public class space/kscience/kmath/viktor/ViktorFieldND : space/kscience/kmath/vi public synthetic fun getOne ()Ljava/lang/Object; public synthetic fun getOne ()Lspace/kscience/kmath/nd/StructureND; public fun getOne ()Lspace/kscience/kmath/viktor/ViktorStructureND; - public fun getShape ()[I + public fun getShape-IIYLAfE ()[I public synthetic fun getZero ()Ljava/lang/Object; public synthetic fun getZero ()Lspace/kscience/kmath/nd/StructureND; public fun getZero ()Lspace/kscience/kmath/viktor/ViktorStructureND; @@ -85,8 +85,8 @@ public class space/kscience/kmath/viktor/ViktorFieldOpsND : space/kscience/kmath public fun sin (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/viktor/ViktorStructureND; public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; public fun sinh (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/viktor/ViktorStructureND; - public synthetic fun structureND ([ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; - public fun structureND ([ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/viktor/ViktorStructureND; + public synthetic fun structureND-qL90JFI ([ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; + public fun structureND-qL90JFI ([ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/viktor/ViktorStructureND; public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; public fun tan (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/viktor/ViktorStructureND; public synthetic fun times (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; @@ -112,7 +112,7 @@ public final class space/kscience/kmath/viktor/ViktorStructureND : space/kscienc public fun get ([I)Ljava/lang/Double; public synthetic fun get ([I)Ljava/lang/Object; public final fun getF64Buffer ()Lorg/jetbrains/bio/viktor/F64Array; - public fun getShape ()[I + public fun getShape-IIYLAfE ()[I public fun set ([ID)V public synthetic fun set ([ILjava/lang/Object;)V } -- 2.34.1 From 8cdbc8dbbe0ece37356f55c385185acac32a6b29 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 9 May 2023 20:12:18 +0300 Subject: [PATCH 273/275] Add opt-ins --- kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt | 3 +++ .../kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt | 2 ++ .../kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt | 2 ++ 3 files changed, 7 insertions(+) diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt index c6b241e5c..7c397d5a0 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/ast/utils.kt @@ -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(UnstableKMathAPI::class) + package space.kscience.kmath.ast +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.MST import space.kscience.kmath.expressions.Symbol diff --git a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt index 0a85d5f24..132f9f1bd 100644 --- a/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt +++ b/kmath-ast/src/jsTest/kotlin/space/kscience/kmath/wasm/TestWasmSpecific.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.wasm +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.expressions.MstExtendedField import space.kscience.kmath.expressions.MstRing import space.kscience.kmath.expressions.invoke @@ -15,6 +16,7 @@ import space.kscience.kmath.operations.invoke import kotlin.test.Test import kotlin.test.assertEquals +@OptIn(UnstableKMathAPI::class) internal class TestWasmSpecific { @Test fun int() { diff --git a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt index 042777c8a..ccd89f063 100644 --- a/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt +++ b/kmath-kotlingrad/src/test/kotlin/space/kscience/kmath/kotlingrad/AdaptingTests.kt @@ -6,6 +6,7 @@ package space.kscience.kmath.kotlingrad import ai.hypergraph.kotlingrad.api.* +import space.kscience.kmath.UnstableKMathAPI import space.kscience.kmath.asm.compileToExpression import space.kscience.kmath.ast.parseMath import space.kscience.kmath.expressions.MstNumericAlgebra @@ -17,6 +18,7 @@ import kotlin.test.assertEquals import kotlin.test.assertTrue import kotlin.test.fail +@OptIn(UnstableKMathAPI::class) internal class AdaptingTests { @Test fun symbol() { -- 2.34.1 From debcef4c9afbe7a2a517799750c89d7ed58d5dc6 Mon Sep 17 00:00:00 2001 From: SPC-code <112205870+SPC-code@users.noreply.github.com> Date: Tue, 9 May 2023 20:34:29 +0300 Subject: [PATCH 274/275] Update README.md change space shield address --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 03e803180..c61bc946f 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382) ![Gradle build](https://github.com/SciProgCentre/kmath/workflows/Gradle%20build/badge.svg) [![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22) -[![Space](https://img.shields.io/badge/dynamic/xml?color=orange&label=Space&query=//metadata/versioning/latest&url=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fspace%2Fkscience%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/) +[![Space](https://img.shields.io/badge/dynamic/xml?color=orange&label=Space&query=//metadata/versioning/latest&url=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fspace%2Fkscience%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/spc/p/sci/maven/space/kscience/) # KMath @@ -325,4 +325,4 @@ Gradle `6.0+` is required for multiplatform artifacts. The project requires a lot of additional work. The most important thing we need is a feedback about what features are required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues marked with -[waiting for a hero](https://github.com/SciProgCentre/kmath/labels/waiting%20for%20a%20hero) label. \ No newline at end of file +[waiting for a hero](https://github.com/SciProgCentre/kmath/labels/waiting%20for%20a%20hero) label. -- 2.34.1 From 378180ba09863160074b2296793bd8547c310a88 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 12 May 2023 20:57:55 +0300 Subject: [PATCH 275/275] Pre-release fixes --- benchmarks/build.gradle.kts | 5 +- build.gradle.kts | 2 +- buildSrc/build.gradle.kts | 11 +- buildSrc/settings.gradle.kts | 1 + .../benchmarks/addBenchmarkProperties.kt | 5 +- examples/build.gradle.kts | 4 +- .../kscience/kmath/expressions/autodiff.kt | 18 +- gradle/wrapper/gradle-wrapper.properties | 2 +- kmath-ast/build.gradle.kts | 2 +- kmath-core/api/kmath-core.api | 350 ------------------ kmath-core/build.gradle.kts | 12 +- kmath-jafama/build.gradle.kts | 6 +- kmath-jupyter/build.gradle.kts | 4 - kmath-kotlingrad/build.gradle.kts | 2 +- kmath-memory/build.gradle.kts | 3 +- kmath-optimization/build.gradle.kts | 3 - kmath-tensors/build.gradle.kts | 7 - test-utils/api/test-utils.api | 32 ++ 18 files changed, 65 insertions(+), 404 deletions(-) create mode 100644 test-utils/api/test-utils.api diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index 3a985cbb4..24471a9e4 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -29,6 +29,9 @@ kotlin { all { languageSettings { progressiveMode = true + optIn("kotlin.contracts.ExperimentalContracts") + optIn("kotlin.ExperimentalUnsignedTypes") + optIn("space.kscience.kmath.UnstableKMathAPI") } } @@ -153,7 +156,7 @@ kotlin.sourceSets.all { with(languageSettings) { optIn("kotlin.contracts.ExperimentalContracts") optIn("kotlin.ExperimentalUnsignedTypes") - optIn("space.kscience.kmath.misc.UnstableKMathAPI") + optIn("space.kscience.kmath.UnstableKMathAPI") } } diff --git a/build.gradle.kts b/build.gradle.kts index 40ae9f210..fb2f7d8c7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -75,6 +75,6 @@ ksciencePublish { sonatype() } -apiValidation.nonPublicMarkers.add("space.kscience.kmath.misc.UnstableKMathAPI") +apiValidation.nonPublicMarkers.add("space.kscience.kmath.UnstableKMathAPI") val multikVersion by extra("0.2.0") diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index afa36ed1e..734f60091 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -3,8 +3,6 @@ plugins { `version-catalog` } -java.targetCompatibility = JavaVersion.VERSION_11 - repositories { mavenLocal() maven("https://repo.kotlin.link") @@ -26,6 +24,11 @@ dependencies { implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.+") } -kotlin.sourceSets.all { - languageSettings.optIn("kotlin.OptIn") +kotlin{ + jvmToolchain{ + languageVersion.set(JavaLanguageVersion.of(11)) + } + sourceSets.all { + languageSettings.optIn("kotlin.OptIn") + } } diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts index 02111ba37..e6b69b0b3 100644 --- a/buildSrc/settings.gradle.kts +++ b/buildSrc/settings.gradle.kts @@ -2,6 +2,7 @@ * Copyright 2018-2021 KMath contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ +rootProject.name = "kmath" enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") 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 61193790b..a3a475885 100644 --- a/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt +++ b/buildSrc/src/main/kotlin/space/kscience/kmath/benchmarks/addBenchmarkProperties.kt @@ -5,9 +5,9 @@ package space.kscience.kmath.benchmarks -import kotlinx.benchmark.gradle.BenchmarksExtension import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.fasterxml.jackson.module.kotlin.readValue +import kotlinx.benchmark.gradle.BenchmarksExtension import org.gradle.api.Project import space.kscience.gradle.KScienceReadmeExtension import java.time.LocalDateTime @@ -16,6 +16,7 @@ import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatterBuilder import java.time.format.SignStyle import java.time.temporal.ChronoField.* +import java.util.* private val ISO_DATE_TIME: DateTimeFormatter = DateTimeFormatterBuilder().run { parseCaseInsensitive() @@ -52,7 +53,7 @@ fun Project.addBenchmarkProperties() { rootProject.subprojects.forEach { p -> p.extensions.findByType(KScienceReadmeExtension::class.java)?.run { benchmarksProject.extensions.findByType(BenchmarksExtension::class.java)?.configurations?.forEach { cfg -> - property("benchmark${cfg.name.capitalize()}") { + property("benchmark${cfg.name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }}") { val launches = benchmarksProject.buildDir.resolve("reports/benchmarks/${cfg.name}") val resDirectory = launches.listFiles()?.maxByOrNull { diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 50708eaa9..7f2abc852 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -58,10 +58,10 @@ dependencies { kotlin { jvmToolchain(11) sourceSets.all { - with(languageSettings) { + languageSettings { optIn("kotlin.contracts.ExperimentalContracts") optIn("kotlin.ExperimentalUnsignedTypes") - optIn("space.kscience.kmath.misc.UnstableKMathAPI") + optIn("space.kscience.kmath.UnstableKMathAPI") } } } diff --git a/examples/src/main/kotlin/space/kscience/kmath/expressions/autodiff.kt b/examples/src/main/kotlin/space/kscience/kmath/expressions/autodiff.kt index b1e14591a..863d6be7a 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/expressions/autodiff.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/expressions/autodiff.kt @@ -26,7 +26,7 @@ fun main() { } // Then we can evaluate it at any point ((-1, -1) in the case): - println(someExpression(mapOf(x to -1.0, y to -1.0))) + println(someExpression(x to -1.0, y to -1.0)) // >>> -2.0 // We can also construct its partial derivatives: @@ -35,23 +35,23 @@ fun main() { val dxdxExpression = someExpression.derivative(x, x) // ∂^2/∂x^2. Must be `0` // We can evaluate them as well - println(dxExpression(mapOf(x to 57.0, y to 6.0))) + println(dxExpression(x to 57.0, y to 6.0)) // >>> 7.0 - println(dyExpression(mapOf(x to -1.0, y to 179.0))) + println(dyExpression(x to -1.0, y to 179.0)) // >>> 0.0 - println(dxdxExpression(mapOf(x to 239.0, y to 30.0))) + println(dxdxExpression(x to 239.0, y to 30.0)) // >>> 0.0 // You can also provide extra arguments that obviously won't affect the result: - println(dxExpression(mapOf(x to 57.0, y to 6.0, z to 42.0))) + println(dxExpression(x to 57.0, y to 6.0, z to 42.0)) // >>> 7.0 - println(dyExpression(mapOf(x to -1.0, y to 179.0, z to 0.0))) + println(dyExpression(x to -1.0, y to 179.0, z to 0.0)) // >>> 0.0 - println(dxdxExpression(mapOf(x to 239.0, y to 30.0, z to 100_000.0))) + println(dxdxExpression(x to 239.0, y to 30.0, z to 100_000.0)) // >>> 0.0 // But in case you forgot to specify bound symbol's value, exception is thrown: - println( runCatching { someExpression(mapOf(z to 4.0)) } ) + println( runCatching { someExpression(z to 4.0) } ) // >>> Failure(java.lang.IllegalStateException: Symbol 'x' is not supported in ...) // The reason is that the expression is evaluated lazily, @@ -63,7 +63,7 @@ fun main() { x pow 2 } // When you evaluate it via - simpleExpression(mapOf(x to 1.0, y to 57.0, z to 179.0)) + simpleExpression(x to 1.0, y to 57.0, z to 179.0) // lambda above has the context of map `{x: 1.0, y: 57.0, z: 179.0}`. // When x is bound, you can think of it as substitution `x -> 1.0`. // Other values are unused which does not make any problem to us. diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 070cb702f..fae08049a 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.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index c60977862..7cdb745f0 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -46,7 +46,7 @@ kotlin { sourceSets { filter { it.name.contains("test", true) } .map(org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet::languageSettings) - .forEach { it.optIn("space.kscience.kmath.misc.UnstableKMathAPI") } + .forEach { it.optIn("space.kscience.kmath.UnstableKMathAPI") } } } diff --git a/kmath-core/api/kmath-core.api b/kmath-core/api/kmath-core.api index e3c33e8c6..42d8277bd 100644 --- a/kmath-core/api/kmath-core.api +++ b/kmath-core/api/kmath-core.api @@ -1,98 +1,22 @@ -public abstract interface class space/kscience/kmath/data/ColumnarData { - public abstract fun get (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/structures/Buffer; - public abstract fun getSize ()I -} - public final class space/kscience/kmath/data/ColumnarDataKt { - public static final fun asColumnarData (Lspace/kscience/kmath/nd/Structure2D;Ljava/util/Map;)Lspace/kscience/kmath/data/ColumnarData; - public static final fun getIndices (Lspace/kscience/kmath/data/ColumnarData;)Lkotlin/ranges/IntRange; -} - -public abstract interface class space/kscience/kmath/data/XYColumnarData : space/kscience/kmath/data/ColumnarData { - public static final field Companion Lspace/kscience/kmath/data/XYColumnarData$Companion; - public fun get (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/structures/Buffer; - public abstract fun getX ()Lspace/kscience/kmath/structures/Buffer; - public abstract fun getY ()Lspace/kscience/kmath/structures/Buffer; } public final class space/kscience/kmath/data/XYColumnarData$Companion { - public final fun of (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/data/XYColumnarData; } public final class space/kscience/kmath/data/XYColumnarDataKt { - public static final fun asXYData (Lspace/kscience/kmath/data/ColumnarData;Lspace/kscience/kmath/expressions/Symbol;Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/data/XYColumnarData; - public static final fun asXYData (Lspace/kscience/kmath/nd/Structure2D;II)Lspace/kscience/kmath/data/XYColumnarData; - public static synthetic fun asXYData$default (Lspace/kscience/kmath/nd/Structure2D;IIILjava/lang/Object;)Lspace/kscience/kmath/data/XYColumnarData; -} - -public abstract interface class space/kscience/kmath/data/XYErrorColumnarData : space/kscience/kmath/data/XYColumnarData { - public static final field Companion Lspace/kscience/kmath/data/XYErrorColumnarData$Companion; - public fun get (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/structures/Buffer; - public abstract fun getYErr ()Lspace/kscience/kmath/structures/Buffer; } public final class space/kscience/kmath/data/XYErrorColumnarData$Companion { public final fun of (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/data/XYErrorColumnarData; } -public abstract interface class space/kscience/kmath/data/XYZColumnarData : space/kscience/kmath/data/XYColumnarData { - public fun get (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/structures/Buffer; - public abstract fun getZ ()Lspace/kscience/kmath/structures/Buffer; -} - public abstract interface class space/kscience/kmath/domains/Domain { public abstract fun contains (Lspace/kscience/kmath/structures/Buffer;)Z public abstract fun getDimension ()I } -public abstract class space/kscience/kmath/domains/Domain1D : space/kscience/kmath/domains/Domain { - public fun (Lkotlin/ranges/ClosedRange;)V - public final fun contains (Ljava/lang/Comparable;)Z - public fun contains (Lspace/kscience/kmath/structures/Buffer;)Z - public fun getDimension ()I - public final fun getRange ()Lkotlin/ranges/ClosedRange; -} - public final class space/kscience/kmath/domains/Domain1DKt { - public static final fun getCenter (Lspace/kscience/kmath/domains/Domain1D;)D -} - -public abstract interface class space/kscience/kmath/domains/DoubleDomain : space/kscience/kmath/domains/Domain { - public abstract fun getLowerBound (I)D - public abstract fun getUpperBound (I)D - public abstract fun volume ()D -} - -public final class space/kscience/kmath/domains/DoubleDomain1D : space/kscience/kmath/domains/Domain1D, space/kscience/kmath/domains/DoubleDomain { - public fun (Lkotlin/ranges/ClosedFloatingPointRange;)V - public fun equals (Ljava/lang/Object;)Z - public final fun getDoubleRange ()Lkotlin/ranges/ClosedFloatingPointRange; - public fun getLowerBound (I)D - public fun getUpperBound (I)D - public fun hashCode ()I - public fun toString ()Ljava/lang/String; - public fun volume ()D -} - -public final class space/kscience/kmath/domains/HyperSquareDomain : space/kscience/kmath/domains/DoubleDomain { - public fun (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)V - public fun contains (Lspace/kscience/kmath/structures/Buffer;)Z - public final fun getCenter-Dv3HvWU ()[D - public fun getDimension ()I - public final fun getLower ()Lspace/kscience/kmath/structures/Buffer; - public fun getLowerBound (I)D - public final fun getUpper ()Lspace/kscience/kmath/structures/Buffer; - public fun getUpperBound (I)D - public fun volume ()D -} - -public final class space/kscience/kmath/domains/UnconstrainedDomain : space/kscience/kmath/domains/DoubleDomain { - public fun (I)V - public fun contains (Lspace/kscience/kmath/structures/Buffer;)Z - public fun getDimension ()I - public fun getLowerBound (I)D - public fun getUpperBound (I)D - public fun volume ()D } public abstract interface class space/kscience/kmath/expressions/AutoDiffProcessor { @@ -104,43 +28,7 @@ public class space/kscience/kmath/expressions/AutoDiffValue { public final fun getValue ()Ljava/lang/Object; } -public abstract interface class space/kscience/kmath/expressions/DS { - public abstract fun getData ()Lspace/kscience/kmath/structures/Buffer; - public abstract fun getDerivativeAlgebra ()Lspace/kscience/kmath/expressions/DSAlgebra; -} - -public abstract class space/kscience/kmath/expressions/DSAlgebra : space/kscience/kmath/expressions/ExpressionAlgebra, space/kscience/kmath/expressions/SymbolIndexer { - public fun (Lspace/kscience/kmath/operations/Ring;ILjava/util/Map;)V - protected final fun DS (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/DSAlgebra$DSSymbol; - public final fun bindSymbol (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/DSAlgebra$DSSymbol; - public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/DSAlgebra$DSSymbol; - public final fun bindSymbolOrNull (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/DSAlgebra$DSSymbol; - public synthetic fun const (Ljava/lang/Object;)Ljava/lang/Object; - public fun const (Ljava/lang/Object;)Lspace/kscience/kmath/expressions/DS; - public final fun derivative (Lspace/kscience/kmath/expressions/DS;Ljava/util/List;)Ljava/lang/Object; - public final fun derivative (Lspace/kscience/kmath/expressions/DS;[Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; - public final fun getAlgebra ()Lspace/kscience/kmath/operations/Ring; - public final fun getCompiler ()Lspace/kscience/kmath/expressions/DSCompiler; - public final fun getOrder ()I - public fun getSymbols ()Ljava/util/List; - public final fun ofDerivatives ([Ljava/lang/Object;)Lspace/kscience/kmath/expressions/DS; - public final fun variable (ILjava/lang/Object;)Lspace/kscience/kmath/expressions/DS; -} - -public final class space/kscience/kmath/expressions/DSAlgebra$DSSymbol : space/kscience/kmath/expressions/DS, space/kscience/kmath/expressions/Symbol { - public fun getData ()Lspace/kscience/kmath/structures/Buffer; - public fun getDerivativeAlgebra ()Lspace/kscience/kmath/expressions/DSAlgebra; - public fun getIdentity ()Ljava/lang/String; -} - public final class space/kscience/kmath/expressions/DSAlgebraKt { - public static final fun derivative (Lspace/kscience/kmath/expressions/DS;Ljava/util/List;)Ljava/lang/Object; - public static final fun derivative (Lspace/kscience/kmath/expressions/DS;[Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; - public static final fun getAutodiff (Lkotlin/jvm/internal/DoubleCompanionObject;)Lspace/kscience/kmath/expressions/DSFieldProcessor; - public static final fun getValue (Lspace/kscience/kmath/expressions/DS;)Ljava/lang/Object; } public final class space/kscience/kmath/expressions/DSCompiler { @@ -153,91 +41,6 @@ public final class space/kscience/kmath/expressions/DSCompiler { public final fun getSizes ()[[I } -public final class space/kscience/kmath/expressions/DSField : space/kscience/kmath/expressions/DSRing, space/kscience/kmath/operations/ExtendedField { - public fun (Lspace/kscience/kmath/operations/ExtendedField;ILjava/util/Map;)V - public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object; - public fun acos (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun acosh (Ljava/lang/Object;)Ljava/lang/Object; - public fun acosh (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun asin (Ljava/lang/Object;)Ljava/lang/Object; - public fun asin (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun asinh (Ljava/lang/Object;)Ljava/lang/Object; - public fun asinh (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun atan (Ljava/lang/Object;)Ljava/lang/Object; - public fun atan (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun atanh (Ljava/lang/Object;)Ljava/lang/Object; - public fun atanh (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object; - public fun cos (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object; - public fun cosh (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun divide (Lspace/kscience/kmath/expressions/DS;Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun exp (Ljava/lang/Object;)Ljava/lang/Object; - public fun exp (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun ln (Ljava/lang/Object;)Ljava/lang/Object; - public fun ln (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; - public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun power (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun power (Lspace/kscience/kmath/expressions/DS;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/DS; - public final fun power (Lspace/kscience/kmath/expressions/DS;Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun sin (Ljava/lang/Object;)Ljava/lang/Object; - public fun sin (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun sinh (Ljava/lang/Object;)Ljava/lang/Object; - public fun sinh (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun sqrt (Ljava/lang/Object;)Ljava/lang/Object; - public fun sqrt (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun tan (Ljava/lang/Object;)Ljava/lang/Object; - public fun tan (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun tanh (Ljava/lang/Object;)Ljava/lang/Object; - public fun tanh (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; -} - -public final class space/kscience/kmath/expressions/DSFieldExpression : space/kscience/kmath/expressions/DifferentiableExpression { - public fun (Lspace/kscience/kmath/operations/ExtendedField;Lkotlin/jvm/functions/Function1;)V - public fun derivativeOrNull (Ljava/util/List;)Lspace/kscience/kmath/expressions/Expression; - public final fun getAlgebra ()Lspace/kscience/kmath/operations/ExtendedField; - public final fun getFunction ()Lkotlin/jvm/functions/Function1; - public fun invoke (Ljava/util/Map;)Ljava/lang/Object; -} - -public final class space/kscience/kmath/expressions/DSFieldProcessor : space/kscience/kmath/expressions/AutoDiffProcessor { - public fun (Lspace/kscience/kmath/operations/ExtendedField;)V - public fun differentiate (Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/DifferentiableExpression; - public final fun getAlgebra ()Lspace/kscience/kmath/operations/ExtendedField; -} - -public class space/kscience/kmath/expressions/DSRing : space/kscience/kmath/expressions/DSAlgebra, space/kscience/kmath/operations/NumbersAddOps, space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/Ring, space/kscience/kmath/operations/ScaleOperations { - public fun (Lspace/kscience/kmath/operations/Ring;ILjava/util/Map;)V - public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun add (Lspace/kscience/kmath/expressions/DS;Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/DSAlgebra$DSSymbol; - public final fun getElementBufferFactory ()Lspace/kscience/kmath/structures/MutableBufferFactory; - public synthetic fun getOne ()Ljava/lang/Object; - public fun getOne ()Lspace/kscience/kmath/expressions/DS; - public synthetic fun getZero ()Ljava/lang/Object; - public fun getZero ()Lspace/kscience/kmath/expressions/DS; - protected final fun mapData (Lspace/kscience/kmath/expressions/DS;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/expressions/DS; - protected final fun mapDataIndexed (Lspace/kscience/kmath/expressions/DS;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun minus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Ljava/lang/Number;Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun multiply (Lspace/kscience/kmath/expressions/DS;Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object; - public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun plus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Ljava/lang/Number;Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun plus (Lspace/kscience/kmath/expressions/DS;Ljava/lang/Number;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun scale (Ljava/lang/Object;D)Ljava/lang/Object; - public fun scale (Lspace/kscience/kmath/expressions/DS;D)Lspace/kscience/kmath/expressions/DS; - protected final fun transformDataBuffer (Lspace/kscience/kmath/expressions/DS;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/expressions/DS; - public synthetic fun unaryMinus (Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryMinus (Lspace/kscience/kmath/expressions/DS;)Lspace/kscience/kmath/expressions/DS; -} - public final class space/kscience/kmath/expressions/DerivationResult { public fun (Ljava/lang/Object;Ljava/util/Map;Lspace/kscience/kmath/operations/Field;)V public final fun derivative (Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; @@ -246,16 +49,6 @@ public final class space/kscience/kmath/expressions/DerivationResult { public final fun getValue ()Ljava/lang/Object; } -public final class space/kscience/kmath/expressions/DerivativeStructureRingExpression : space/kscience/kmath/expressions/DifferentiableExpression { - public fun (Lspace/kscience/kmath/operations/Ring;Lspace/kscience/kmath/structures/MutableBufferFactory;Lkotlin/jvm/functions/Function1;)V - public synthetic fun (Lspace/kscience/kmath/operations/Ring;Lspace/kscience/kmath/structures/MutableBufferFactory;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public fun derivativeOrNull (Ljava/util/List;)Lspace/kscience/kmath/expressions/Expression; - public final fun getAlgebra ()Lspace/kscience/kmath/operations/Ring; - public final fun getElementBufferFactory ()Lspace/kscience/kmath/structures/MutableBufferFactory; - public final fun getFunction ()Lkotlin/jvm/functions/Function1; - public fun invoke (Ljava/util/Map;)Ljava/lang/Object; -} - public final class space/kscience/kmath/expressions/DiffExpressionWithDefault : space/kscience/kmath/expressions/DifferentiableExpression { public fun (Lspace/kscience/kmath/expressions/DifferentiableExpression;Ljava/util/Map;)V public fun derivativeOrNull (Ljava/util/List;)Lspace/kscience/kmath/expressions/Expression; @@ -275,14 +68,6 @@ public final class space/kscience/kmath/expressions/DifferentiableExpressionKt { public static final fun derivative (Lspace/kscience/kmath/expressions/SpecialDifferentiableExpression;[Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/Expression; } -public abstract interface class space/kscience/kmath/expressions/DoubleExpression : space/kscience/kmath/expressions/Expression { - public static final field Companion Lspace/kscience/kmath/expressions/DoubleExpression$Companion; - public abstract fun getIndexer ()Lspace/kscience/kmath/expressions/SymbolIndexer; - public fun invoke (Ljava/util/Map;)Ljava/lang/Double; - public synthetic fun invoke (Ljava/util/Map;)Ljava/lang/Object; - public abstract fun invoke ([D)D -} - public final class space/kscience/kmath/expressions/DoubleExpression$Companion { } @@ -298,13 +83,7 @@ public final class space/kscience/kmath/expressions/ExpressionKt { public static final fun callByString (Lspace/kscience/kmath/expressions/Expression;[Lkotlin/Pair;)Ljava/lang/Object; public static final fun callBySymbol (Lspace/kscience/kmath/expressions/Expression;[Lkotlin/Pair;)Ljava/lang/Object; public static final fun getBinding (Lspace/kscience/kmath/expressions/ExpressionAlgebra;)Lkotlin/properties/ReadOnlyProperty; - public static final fun invoke (Lspace/kscience/kmath/expressions/DoubleExpression;)D - public static final fun invoke (Lspace/kscience/kmath/expressions/DoubleExpression;[D)D public static final fun invoke (Lspace/kscience/kmath/expressions/Expression;)Ljava/lang/Object; - public static final fun invoke (Lspace/kscience/kmath/expressions/IntExpression;)I - public static final fun invoke (Lspace/kscience/kmath/expressions/IntExpression;[I)I - public static final fun invoke (Lspace/kscience/kmath/expressions/LongExpression;)J - public static final fun invoke (Lspace/kscience/kmath/expressions/LongExpression;[J)J } public final class space/kscience/kmath/expressions/ExpressionWithDefault : space/kscience/kmath/expressions/Expression { @@ -410,25 +189,9 @@ public class space/kscience/kmath/expressions/FunctionalExpressionRing : space/k public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; } -public abstract interface class space/kscience/kmath/expressions/IntExpression : space/kscience/kmath/expressions/Expression { - public static final field Companion Lspace/kscience/kmath/expressions/IntExpression$Companion; - public abstract fun getIndexer ()Lspace/kscience/kmath/expressions/SymbolIndexer; - public fun invoke (Ljava/util/Map;)Ljava/lang/Integer; - public synthetic fun invoke (Ljava/util/Map;)Ljava/lang/Object; - public abstract fun invoke ([I)I -} - public final class space/kscience/kmath/expressions/IntExpression$Companion { } -public abstract interface class space/kscience/kmath/expressions/LongExpression : space/kscience/kmath/expressions/Expression { - public static final field Companion Lspace/kscience/kmath/expressions/LongExpression$Companion; - public abstract fun getIndexer ()Lspace/kscience/kmath/expressions/SymbolIndexer; - public fun invoke (Ljava/util/Map;)Ljava/lang/Long; - public synthetic fun invoke (Ljava/util/Map;)Ljava/lang/Object; - public abstract fun invoke ([J)J -} - public final class space/kscience/kmath/expressions/LongExpression$Companion { } @@ -590,22 +353,6 @@ public final class space/kscience/kmath/expressions/MstGroup : space/kscience/km public fun unaryPlus (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary; } -public final class space/kscience/kmath/expressions/MstLogicAlgebra : space/kscience/kmath/operations/LogicAlgebra { - public static final field INSTANCE Lspace/kscience/kmath/expressions/MstLogicAlgebra; - public synthetic fun and (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun and (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; - public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; - public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST; - public synthetic fun const (Z)Ljava/lang/Object; - public fun const (Z)Lspace/kscience/kmath/expressions/Symbol; - public synthetic fun not (Ljava/lang/Object;)Ljava/lang/Object; - public fun not (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; - public synthetic fun or (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun or (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; - public synthetic fun xor (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun xor (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST; -} - public final class space/kscience/kmath/expressions/MstNumericAlgebra : space/kscience/kmath/operations/NumericAlgebra { public static final field INSTANCE Lspace/kscience/kmath/expressions/MstNumericAlgebra; public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; @@ -778,20 +525,6 @@ public final class space/kscience/kmath/expressions/SimpleAutoDiffKt { public static final fun tanh (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue; } -public final class space/kscience/kmath/expressions/SimpleSymbolIndexer : space/kscience/kmath/expressions/SymbolIndexer { - public static final synthetic fun box-impl (Ljava/util/List;)Lspace/kscience/kmath/expressions/SimpleSymbolIndexer; - public static fun constructor-impl (Ljava/util/List;)Ljava/util/List; - public fun equals (Ljava/lang/Object;)Z - public static fun equals-impl (Ljava/util/List;Ljava/lang/Object;)Z - public static final fun equals-impl0 (Ljava/util/List;Ljava/util/List;)Z - public fun getSymbols ()Ljava/util/List; - public fun hashCode ()I - public static fun hashCode-impl (Ljava/util/List;)I - public fun toString ()Ljava/lang/String; - public static fun toString-impl (Ljava/util/List;)Ljava/lang/String; - public final synthetic fun unbox-impl ()Ljava/util/List; -} - public abstract interface class space/kscience/kmath/expressions/SpecialDifferentiableExpression : space/kscience/kmath/expressions/DifferentiableExpression { public abstract fun derivativeOrNull (Ljava/util/List;)Lspace/kscience/kmath/expressions/Expression; } @@ -810,25 +543,7 @@ public final class space/kscience/kmath/expressions/Symbol$Companion { public final fun getZError ()Lspace/kscience/kmath/expressions/Symbol; } -public abstract interface class space/kscience/kmath/expressions/SymbolIndexer { - public fun get (Ljava/util/List;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; - public fun get (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/expressions/Symbol;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; - public fun get (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; - public fun get ([DLspace/kscience/kmath/expressions/Symbol;)D - public fun get ([Ljava/lang/Object;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object; - public abstract fun getSymbols ()Ljava/util/List; - public fun indexOf (Lspace/kscience/kmath/expressions/Symbol;)I - public fun toDoubleArray (Ljava/util/Map;)[D - public fun toList (Ljava/util/Map;)Ljava/util/List; - public fun toMap (Lspace/kscience/kmath/structures/Buffer;)Ljava/util/Map; - public fun toMap ([D)Ljava/util/Map; - public fun toPoint (Ljava/util/Map;Lspace/kscience/kmath/structures/BufferFactory;)Lspace/kscience/kmath/structures/Buffer; - public fun toPoint-Udx-57Q (Ljava/util/Map;)[D -} - public final class space/kscience/kmath/expressions/SymbolIndexerKt { - public static final fun withSymbols (Ljava/util/Collection;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun withSymbols ([Lspace/kscience/kmath/expressions/Symbol;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; } public final class space/kscience/kmath/expressions/SymbolKt { @@ -925,7 +640,6 @@ public abstract interface class space/kscience/kmath/linear/LinearSpace { public static final field Companion Lspace/kscience/kmath/linear/LinearSpace$Companion; public abstract fun buildMatrix (IILkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/Structure2D; public abstract fun buildVector (ILkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; - public fun computeFeature (Lspace/kscience/kmath/nd/Structure2D;Lkotlin/reflect/KClass;)Lspace/kscience/kmath/nd/StructureFeature; public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public fun dot (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public abstract fun getElementAlgebra ()Lspace/kscience/kmath/operations/Ring; @@ -990,11 +704,9 @@ public final class space/kscience/kmath/linear/MatrixBuilder { public final class space/kscience/kmath/linear/MatrixBuilderKt { public static final fun column (Lspace/kscience/kmath/linear/LinearSpace;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/Structure2D; public static final fun column (Lspace/kscience/kmath/linear/LinearSpace;[Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; - public static final fun matrix (Lspace/kscience/kmath/linear/LinearSpace;II)Lspace/kscience/kmath/linear/MatrixBuilder; public static final fun row (Lspace/kscience/kmath/linear/LinearSpace;ILkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/nd/Structure2D; public static final fun row (Lspace/kscience/kmath/linear/LinearSpace;[Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D; public static final fun symmetric (Lspace/kscience/kmath/linear/MatrixBuilder;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/Structure2D; - public static final fun vector (Lspace/kscience/kmath/linear/LinearSpace;[Ljava/lang/Object;)Lspace/kscience/kmath/structures/Buffer; } public abstract interface class space/kscience/kmath/linear/MatrixFeature : space/kscience/kmath/nd/StructureFeature { @@ -1023,7 +735,6 @@ public final class space/kscience/kmath/linear/MatrixWrapper : space/kscience/km } public final class space/kscience/kmath/linear/MatrixWrapperKt { - public static final fun getOrigin (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; public static final fun one (Lspace/kscience/kmath/linear/LinearSpace;II)Lspace/kscience/kmath/nd/Structure2D; public static final fun plus (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/linear/MatrixFeature;)Lspace/kscience/kmath/linear/MatrixWrapper; public static final fun transpose (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D; @@ -1163,11 +874,6 @@ public final class space/kscience/kmath/misc/NumbersJVMKt { } public final class space/kscience/kmath/misc/SortingKt { - public static final fun indicesSorted (Lspace/kscience/kmath/structures/Buffer;)[I - public static final fun indicesSortedBy (Lspace/kscience/kmath/structures/Buffer;Lkotlin/jvm/functions/Function1;)[I - public static final fun indicesSortedByDescending (Lspace/kscience/kmath/structures/Buffer;Lkotlin/jvm/functions/Function1;)[I - public static final fun indicesSortedDescending (Lspace/kscience/kmath/structures/Buffer;)[I - public static final fun indicesSortedWith (Lspace/kscience/kmath/structures/Buffer;Ljava/util/Comparator;)[I public static final fun requireSorted (Lspace/kscience/kmath/structures/Buffer;)V public static final fun sorted (Lspace/kscience/kmath/structures/Buffer;)Lspace/kscience/kmath/structures/Buffer; public static final fun sortedBy (Lspace/kscience/kmath/structures/Buffer;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; @@ -1178,7 +884,6 @@ public final class space/kscience/kmath/misc/SortingKt { public abstract interface class space/kscience/kmath/nd/AlgebraND : space/kscience/kmath/operations/Algebra { public static final field Companion Lspace/kscience/kmath/nd/AlgebraND$Companion; public abstract fun getElementAlgebra ()Lspace/kscience/kmath/operations/Algebra; - public fun getFeature (Lspace/kscience/kmath/nd/StructureND;Lkotlin/reflect/KClass;)Lspace/kscience/kmath/nd/StructureFeature; public fun invoke (Lkotlin/jvm/functions/Function1;Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/StructureND; public fun map (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/nd/StructureND; public fun mapIndexed (Lspace/kscience/kmath/nd/StructureND;Lkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/StructureND; @@ -1317,7 +1022,6 @@ public final class space/kscience/kmath/nd/DoubleFieldNDKt { public static final fun getNdAlgebra (Lspace/kscience/kmath/operations/DoubleField;)Lspace/kscience/kmath/nd/DoubleFieldOpsND; public static final fun ndAlgebra (Lspace/kscience/kmath/operations/DoubleField;[I)Lspace/kscience/kmath/nd/DoubleFieldND; public static final fun ndAlgebra-waz_sdI (Lspace/kscience/kmath/operations/DoubleField;[I)Lspace/kscience/kmath/nd/DoubleFieldND; - public static final fun withNdAlgebra (Lspace/kscience/kmath/operations/DoubleField;[ILkotlin/jvm/functions/Function1;)Ljava/lang/Object; } public abstract class space/kscience/kmath/nd/DoubleFieldOpsND : space/kscience/kmath/nd/BufferedFieldOpsND, space/kscience/kmath/operations/ExtendedFieldOps, space/kscience/kmath/operations/ScaleOperations { @@ -1733,14 +1437,6 @@ public abstract interface class space/kscience/kmath/nd/StructureNDOfInt : space public abstract fun getInt ([I)I } -public final class space/kscience/kmath/nd/VirtualDoubleStructureND : space/kscience/kmath/nd/VirtualStructureND { - public synthetic fun ([ILkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V -} - -public final class space/kscience/kmath/nd/VirtualIntStructureND : space/kscience/kmath/nd/VirtualStructureND { - public synthetic fun ([ILkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V -} - public class space/kscience/kmath/nd/VirtualStructureND : space/kscience/kmath/nd/StructureND { public synthetic fun ([ILkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V public fun get ([I)Ljava/lang/Object; @@ -1758,7 +1454,6 @@ public abstract interface class space/kscience/kmath/operations/Algebra { public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object; public fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; - public fun export (Ljava/lang/Object;)Ljava/lang/Object; public fun getBufferFactory ()Lspace/kscience/kmath/structures/MutableBufferFactory; public fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; @@ -1855,20 +1550,6 @@ public final class space/kscience/kmath/operations/BigIntKt { public static final fun toBigInt-WZ4Q5Ns (I)Lspace/kscience/kmath/operations/BigInt; } -public final class space/kscience/kmath/operations/BooleanAlgebra : space/kscience/kmath/operations/LogicAlgebra { - public static final field INSTANCE Lspace/kscience/kmath/operations/BooleanAlgebra; - public synthetic fun and (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun and (ZZ)Ljava/lang/Boolean; - public fun const (Z)Ljava/lang/Boolean; - public synthetic fun const (Z)Ljava/lang/Object; - public synthetic fun not (Ljava/lang/Object;)Ljava/lang/Object; - public fun not (Z)Ljava/lang/Boolean; - public synthetic fun or (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun or (ZZ)Ljava/lang/Boolean; - public synthetic fun xor (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun xor (ZZ)Ljava/lang/Boolean; -} - public abstract interface class space/kscience/kmath/operations/BufferAlgebra : space/kscience/kmath/operations/Algebra { public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; public fun buffer (I[Ljava/lang/Object;)Lspace/kscience/kmath/structures/Buffer; @@ -1908,14 +1589,12 @@ public final class space/kscience/kmath/operations/BufferAlgebraKt { public final class space/kscience/kmath/operations/BufferExtensionsKt { public static final fun asIterable (Lspace/kscience/kmath/structures/Buffer;)Ljava/lang/Iterable; public static final fun asSequence (Lspace/kscience/kmath/structures/Buffer;)Lkotlin/sequences/Sequence; - public static final fun combineToBuffer (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/BufferFactory;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; public static final fun fold (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; public static final fun foldIndexed (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;Lkotlin/jvm/functions/Function3;)Ljava/lang/Object; public static final fun mapIndexedToBuffer (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/BufferFactory;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer; public static final fun mapToBuffer (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/BufferFactory;Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/structures/Buffer; public static final fun reduce (Lspace/kscience/kmath/structures/Buffer;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; public static final fun toList (Lspace/kscience/kmath/structures/Buffer;)Ljava/util/List; - public static final fun toMutableList (Lspace/kscience/kmath/structures/Buffer;)Ljava/util/List; } public final class space/kscience/kmath/operations/BufferField : space/kscience/kmath/operations/BufferFieldOps, space/kscience/kmath/operations/Field, space/kscience/kmath/operations/WithSize { @@ -2045,7 +1724,6 @@ public abstract class space/kscience/kmath/operations/DoubleBufferOps : space/ks public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public fun minus-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun multiply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun multiply-CZ9oacQ (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;)[D public synthetic fun norm (Ljava/lang/Object;)Ljava/lang/Object; public fun norm (Lspace/kscience/kmath/structures/Buffer;)Ljava/lang/Double; public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @@ -2390,20 +2068,6 @@ public final class space/kscience/kmath/operations/JBigIntegerField : space/ksci public fun unaryMinus (Ljava/math/BigInteger;)Ljava/math/BigInteger; } -public abstract interface class space/kscience/kmath/operations/LogicAlgebra : space/kscience/kmath/operations/Algebra { - public static final field Companion Lspace/kscience/kmath/operations/LogicAlgebra$Companion; - public abstract fun and (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperation (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; - public fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object; - public abstract fun const (Z)Ljava/lang/Object; - public abstract fun not (Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun or (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperation (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1; - public abstract fun xor (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; -} - public final class space/kscience/kmath/operations/LogicAlgebra$Companion { public final fun getFALSE ()Lspace/kscience/kmath/expressions/Symbol; public final fun getTRUE ()Lspace/kscience/kmath/expressions/Symbol; @@ -2438,13 +2102,6 @@ public abstract interface class space/kscience/kmath/operations/Norm { public abstract fun norm (Ljava/lang/Object;)Ljava/lang/Object; } -public abstract interface class space/kscience/kmath/operations/NumbersAddOps : space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/RingOps { - public fun minus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun minus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; - public fun plus (Ljava/lang/Number;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Ljava/lang/Object;Ljava/lang/Number;)Ljava/lang/Object; -} - public final class space/kscience/kmath/operations/NumbersKt { public static final fun getAlgebra (Lkotlin/jvm/internal/ByteCompanionObject;)Lspace/kscience/kmath/operations/ByteRing; public static final fun getAlgebra (Lkotlin/jvm/internal/DoubleCompanionObject;)Lspace/kscience/kmath/operations/DoubleField; @@ -2600,7 +2257,6 @@ public final class space/kscience/kmath/structures/BufferExpanded : space/kscien public final fun getOffset ()I public fun getOrigin ()Lspace/kscience/kmath/structures/Buffer; public fun getSize ()I - public fun originIndex (I)I public fun toString ()Ljava/lang/String; } @@ -2623,8 +2279,6 @@ public final class space/kscience/kmath/structures/BufferKt { } public final class space/kscience/kmath/structures/BufferPrimitiveAccessKt { - public static final fun getDouble (Lspace/kscience/kmath/structures/Buffer;I)D - public static final fun getInt (Lspace/kscience/kmath/structures/Buffer;I)I } public final class space/kscience/kmath/structures/BufferSlice : space/kscience/kmath/structures/BufferView { @@ -2635,14 +2289,12 @@ public final class space/kscience/kmath/structures/BufferSlice : space/kscience/ public fun getOrigin ()Lspace/kscience/kmath/structures/Buffer; public fun getSize ()I public fun iterator ()Ljava/util/Iterator; - public fun originIndex (I)I public fun toString ()Ljava/lang/String; } public abstract interface class space/kscience/kmath/structures/BufferView : space/kscience/kmath/structures/Buffer { public fun get (I)Ljava/lang/Object; public abstract fun getOrigin ()Lspace/kscience/kmath/structures/Buffer; - public abstract fun originIndex (I)I } public final class space/kscience/kmath/structures/BufferViewKt { @@ -2958,7 +2610,6 @@ public final class space/kscience/kmath/structures/PermutedBuffer : space/kscien public fun getOrigin ()Lspace/kscience/kmath/structures/Buffer; public fun getSize ()I public fun iterator ()Ljava/util/Iterator; - public fun originIndex (I)I public fun toString ()Ljava/lang/String; } @@ -2970,7 +2621,6 @@ public final class space/kscience/kmath/structures/PermutedMutableBuffer : space public fun getOrigin ()Lspace/kscience/kmath/structures/MutableBuffer; public fun getSize ()I public fun iterator ()Ljava/util/Iterator; - public fun originIndex (I)I public fun set (ILjava/lang/Object;)V public fun toString ()Ljava/lang/String; } diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts index 08411be59..8c622e8b0 100644 --- a/kmath-core/build.gradle.kts +++ b/kmath-core/build.gradle.kts @@ -10,9 +10,8 @@ kscience{ browser { testTask { useKarma { - this.webpackConfig.experiments.add("topLevelAwait") + webpackConfig.experiments.add("topLevelAwait") useChromeHeadless() - useConfigDirectory(project.projectDir.resolve("karma.config.d").resolve("wasm")) } } } @@ -33,15 +32,6 @@ kscience{ } } -kotlin.sourceSets { - filter { it.name.contains("test", true) } - .map(org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet::languageSettings) - .forEach { - it.optIn("space.kscience.kmath.misc.PerformancePitfall") - it.optIn("space.kscience.kmath.misc.UnstableKMathAPI") - } -} - readme { description = "Core classes, algebra definitions, basic linear algebra" maturity = space.kscience.gradle.Maturity.DEVELOPMENT diff --git a/kmath-jafama/build.gradle.kts b/kmath-jafama/build.gradle.kts index da77f469d..5a77a97ed 100644 --- a/kmath-jafama/build.gradle.kts +++ b/kmath-jafama/build.gradle.kts @@ -20,8 +20,4 @@ readme { feature("jafama-double", "src/main/kotlin/space/kscience/kmath/jafama/") { "Double ExtendedField implementations based on Jafama" } -} - -kotlin.sourceSets.all { - languageSettings.optIn("space.kscience.kmath.misc.UnstableKMathAPI") -} +} \ No newline at end of file diff --git a/kmath-jupyter/build.gradle.kts b/kmath-jupyter/build.gradle.kts index a600261b3..a0e217177 100644 --- a/kmath-jupyter/build.gradle.kts +++ b/kmath-jupyter/build.gradle.kts @@ -14,10 +14,6 @@ readme { maturity = space.kscience.gradle.Maturity.PROTOTYPE } -kotlin.sourceSets.all { - languageSettings.optIn("space.kscience.kmath.misc.UnstableKMathAPI") -} - tasks.processJupyterApiResources { libraryProducers = listOf("space.kscience.kmath.jupyter.KMathJupyter") } diff --git a/kmath-kotlingrad/build.gradle.kts b/kmath-kotlingrad/build.gradle.kts index cf4a4bc1d..56e191360 100644 --- a/kmath-kotlingrad/build.gradle.kts +++ b/kmath-kotlingrad/build.gradle.kts @@ -5,7 +5,7 @@ plugins { kotlin.sourceSets .filter { it.name.contains("test", true) } .map(org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet::languageSettings) - .forEach { it.optIn("space.kscience.kmath.misc.UnstableKMathAPI") } + .forEach { it.optIn("space.kscience.kmath.UnstableKMathAPI") } description = "Kotlin∇ integration module" diff --git a/kmath-memory/build.gradle.kts b/kmath-memory/build.gradle.kts index 4e5370c0f..8c1e63cb7 100644 --- a/kmath-memory/build.gradle.kts +++ b/kmath-memory/build.gradle.kts @@ -10,9 +10,8 @@ kscience { browser { testTask { useKarma { - this.webpackConfig.experiments.add("topLevelAwait") + webpackConfig.experiments.add("topLevelAwait") useChromeHeadless() - useConfigDirectory(project.projectDir.resolve("karma.config.d").resolve("wasm")) } } } diff --git a/kmath-optimization/build.gradle.kts b/kmath-optimization/build.gradle.kts index 0a8e47728..7250d1f72 100644 --- a/kmath-optimization/build.gradle.kts +++ b/kmath-optimization/build.gradle.kts @@ -9,9 +9,6 @@ kscience{ } kotlin.sourceSets { - all { - languageSettings.optIn("space.kscience.kmath.misc.UnstableKMathAPI") - } commonMain { dependencies { diff --git a/kmath-tensors/build.gradle.kts b/kmath-tensors/build.gradle.kts index d27faeeef..79c39bae7 100644 --- a/kmath-tensors/build.gradle.kts +++ b/kmath-tensors/build.gradle.kts @@ -14,13 +14,6 @@ kscience{ } kotlin.sourceSets { - all { - languageSettings.optIn("space.kscience.kmath.misc.UnstableKMathAPI") - } - - filter { it.name.contains("test", true) } - .map(org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet::languageSettings) - .forEach { it.optIn("space.kscience.kmath.misc.PerformancePitfall") } commonMain { dependencies { diff --git a/test-utils/api/test-utils.api b/test-utils/api/test-utils.api new file mode 100644 index 000000000..fc812a9a6 --- /dev/null +++ b/test-utils/api/test-utils.api @@ -0,0 +1,32 @@ +public final class space/kscience/kmath/testutils/AssertsKt { + public static final fun assertBufferEquals (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;D)V + public static synthetic fun assertBufferEquals$default (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/structures/Buffer;DILjava/lang/Object;)V +} + +public final class space/kscience/kmath/testutils/BufferEqualityKt { + public static final fun contentEquals-2c9zdjM ([D[D)Z + public static final fun contentEqualsArray ([D[D)Z + public static final fun contentEqualsBuffer ([D[D)Z +} + +public final class space/kscience/kmath/testutils/FieldVerifier : space/kscience/kmath/testutils/RingVerifier { + public fun (Lspace/kscience/kmath/operations/Field;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Number;)V + public fun verify ()V +} + +public class space/kscience/kmath/testutils/RingVerifier : space/kscience/kmath/testutils/SpaceVerifier { + public fun (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Number;)V + public fun verify ()V +} + +public class space/kscience/kmath/testutils/SpaceVerifier : space/kscience/kmath/testutils/AlgebraicVerifier { + public fun (Lspace/kscience/kmath/operations/Ring;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Number;)V + public final fun getA ()Ljava/lang/Object; + public synthetic fun getAlgebra ()Lspace/kscience/kmath/operations/Algebra; + public fun getAlgebra ()Lspace/kscience/kmath/operations/Ring; + public final fun getB ()Ljava/lang/Object; + public final fun getC ()Ljava/lang/Object; + public final fun getX ()Ljava/lang/Number; + public fun verify ()V +} + -- 2.34.1