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.

This commit is contained in:
Gleb Minaev 2022-06-17 01:53:40 +03:00
parent eadd521e35
commit b5a94923b5
10 changed files with 1714 additions and 99 deletions

View File

@ -100,14 +100,17 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
* The operation is equivalent to sum of [other] copies of [this]. * The operation is equivalent to sum of [other] copies of [this].
*/ */
public override operator fun ListPolynomial<C>.times(other: Int): ListPolynomial<C> = public override operator fun ListPolynomial<C>.times(other: Int): ListPolynomial<C> =
if (other == 0) zero when (other) {
else ListPolynomial( 0 -> zero
coefficients 1 -> this
.toMutableList() else -> ListPolynomial(
.apply { coefficients
for (deg in indices) this[deg] = this[deg] * other .toMutableList()
} .apply {
) for (deg in indices) this[deg] = this[deg] * other
}
)
}
/** /**
* Returns sum of the integer represented as a polynomial and the polynomial. * Returns sum of the integer represented as a polynomial and the polynomial.
@ -133,34 +136,39 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
* The operation is equivalent to subtraction [this] copies of unit polynomial from [other]. * The operation is equivalent to subtraction [this] copies of unit polynomial from [other].
*/ */
public override operator fun Int.minus(other: ListPolynomial<C>): ListPolynomial<C> = public override operator fun Int.minus(other: ListPolynomial<C>): ListPolynomial<C> =
if (this == 0) other ListPolynomial(
else other.coefficients
ListPolynomial( .toMutableList()
other.coefficients .apply {
.toMutableList() if (this@minus == 0) {
.apply { indices.forEach { this[it] = -this[it] }
forEachIndexed { index, c -> if (index != 0) this[index] = -c } } else {
(1..lastIndex).forEach { this[it] = -this[it] }
val result = this@minus - getOrElse(0) { constantZero } val result = this@minus - getOrElse(0) { constantZero }
if(size == 0) add(result) if (size == 0) add(result)
else this[0] = result else this[0] = result
} }
) }
)
/** /**
* Returns product of the integer represented as a 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]. * The operation is equivalent to sum of [this] copies of [other].
*/ */
public override operator fun Int.times(other: ListPolynomial<C>): ListPolynomial<C> = public override operator fun Int.times(other: ListPolynomial<C>): ListPolynomial<C> =
if (this == 0) zero when (this) {
else ListPolynomial( 0 -> zero
other.coefficients 1 -> other
.toMutableList() else -> ListPolynomial(
.apply { other.coefficients
for (deg in indices) this[deg] = this@times * this[deg] .toMutableList()
} .apply {
) for (deg in indices) this[deg] = this@times * this[deg]
}
)
}
/** /**
* Converts the integer [value] to polynomial. * Converts the integer [value] to polynomial.
@ -192,7 +200,7 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
else ListPolynomial( else ListPolynomial(
toMutableList() toMutableList()
.apply { .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) val result = if (size == 0) this@minus else this@minus - get(0)

View File

@ -98,14 +98,17 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
* The operation is equivalent to sum of [other] copies of [this]. * The operation is equivalent to sum of [other] copies of [this].
*/ */
public override operator fun NumberedPolynomial<C>.times(other: Int): NumberedPolynomial<C> = public override operator fun NumberedPolynomial<C>.times(other: Int): NumberedPolynomial<C> =
if (other == 0) zero when (other) {
else NumberedPolynomialAsIs( 0 -> zero
coefficients 1 -> this
.toMutableMap() else -> NumberedPolynomialAsIs(
.apply { coefficients
for (degs in keys) this[degs] = this[degs]!! * other .toMutableMap()
} .apply {
) for (degs in keys) this[degs] = this[degs]!! * other
}
)
}
/** /**
* Returns sum of the integer represented as a polynomial and the polynomial. * Returns sum of the integer represented as a polynomial and the polynomial.
@ -130,16 +133,20 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
* The operation is equivalent to subtraction [this] copies of unit polynomial from [other]. * The operation is equivalent to subtraction [this] copies of unit polynomial from [other].
*/ */
public override operator fun Int.minus(other: NumberedPolynomial<C>): NumberedPolynomial<C> = public override operator fun Int.minus(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
if (this == 0) other NumberedPolynomialAsIs(
else other.coefficients
NumberedPolynomialAsIs( .toMutableMap()
other.coefficients .apply {
.toMutableMap() if (this@minus == 0) {
.apply { forEach { (key, value) -> this[key] = -value }
} else {
forEach { (key, value) -> if (key.isNotEmpty()) this[key] = -value }
val degs = emptyList<UInt>() val degs = emptyList<UInt>()
this[degs] = this@minus - getOrElse(degs) { constantZero } this[degs] = this@minus - getOrElse(degs) { constantZero }
} }
}
) )
/** /**
* Returns product of the integer represented as a polynomial and the polynomial. * Returns product of the integer represented as a polynomial and the polynomial.
@ -147,14 +154,17 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
* The operation is equivalent to sum of [this] copies of [other]. * The operation is equivalent to sum of [this] copies of [other].
*/ */
public override operator fun Int.times(other: NumberedPolynomial<C>): NumberedPolynomial<C> = public override operator fun Int.times(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
if (this == 0) zero when (this) {
else NumberedPolynomialAsIs( 0 -> zero
other.coefficients 1 -> other
.toMutableMap() else -> NumberedPolynomialAsIs(
.apply { other.coefficients
for (degs in keys) this[degs] = this@times * this[degs]!! .toMutableMap()
} .apply {
) for (degs in keys) this[degs] = this@times * this[degs]!!
}
)
}
/** /**
* Converts the integer [value] to polynomial. * Converts the integer [value] to polynomial.
@ -185,7 +195,7 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
else NumberedPolynomialAsIs( else NumberedPolynomialAsIs(
toMutableMap() toMutableMap()
.apply { .apply {
forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } forEach { (degs, c) -> if (degs.isNotEmpty()) this[degs] = -c }
val degs = emptyList<UInt>() val degs = emptyList<UInt>()
@ -266,7 +276,7 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
override operator fun NumberedPolynomial<C>.plus(other: NumberedPolynomial<C>): NumberedPolynomial<C> = override operator fun NumberedPolynomial<C>.plus(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
NumberedPolynomialAsIs( NumberedPolynomialAsIs(
buildMap(coefficients.size + other.coefficients.size) { 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 } other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value }
} }
) )
@ -276,7 +286,7 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
override operator fun NumberedPolynomial<C>.minus(other: NumberedPolynomial<C>): NumberedPolynomial<C> = override operator fun NumberedPolynomial<C>.minus(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
NumberedPolynomialAsIs( NumberedPolynomialAsIs(
buildMap(coefficients.size + other.coefficients.size) { 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 } other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value }
} }
) )

View File

@ -119,11 +119,13 @@ public class NumberedRationalFunctionSpace<C, A: Ring<C>> (
* Substitutes provided polynomial [argument] into [this] polynomial. * Substitutes provided polynomial [argument] into [this] polynomial.
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
@JvmName("substitutePolynomial")
public inline fun NumberedPolynomial<C>.substitute(argument: Map<Int, NumberedPolynomial<C>>): NumberedPolynomial<C> = substitute(ring, argument) public inline fun NumberedPolynomial<C>.substitute(argument: Map<Int, NumberedPolynomial<C>>): NumberedPolynomial<C> = substitute(ring, argument)
/** /**
* Substitutes provided rational function [argument] into [this] polynomial. * Substitutes provided rational function [argument] into [this] polynomial.
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
@JvmName("substituteRationalFunction")
public inline fun NumberedPolynomial<C>.substitute(argument: Map<Int, NumberedRationalFunction<C>>): NumberedRationalFunction<C> = substitute(ring, argument) public inline fun NumberedPolynomial<C>.substitute(argument: Map<Int, NumberedRationalFunction<C>>): NumberedRationalFunction<C> = substitute(ring, argument)
/** /**
* Substitutes provided constant [argument] into [this] rational function. * Substitutes provided constant [argument] into [this] rational function.
@ -134,11 +136,13 @@ public class NumberedRationalFunctionSpace<C, A: Ring<C>> (
* Substitutes provided polynomial [argument] into [this] rational function. * Substitutes provided polynomial [argument] into [this] rational function.
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
@JvmName("substitutePolynomial")
public inline fun NumberedRationalFunction<C>.substitute(argument: Map<Int, NumberedPolynomial<C>>): NumberedRationalFunction<C> = substitute(ring, argument) public inline fun NumberedRationalFunction<C>.substitute(argument: Map<Int, NumberedPolynomial<C>>): NumberedRationalFunction<C> = substitute(ring, argument)
/** /**
* Substitutes provided rational function [argument] into [this] rational function. * Substitutes provided rational function [argument] into [this] rational function.
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
@JvmName("substituteRationalFunction")
public inline fun NumberedRationalFunction<C>.substitute(argument: Map<Int, NumberedRationalFunction<C>>): NumberedRationalFunction<C> = substitute(ring, argument) public inline fun NumberedRationalFunction<C>.substitute(argument: Map<Int, NumberedRationalFunction<C>>): NumberedRationalFunction<C> = substitute(ring, argument)
/** /**
* Substitutes provided constant [argument] into [this] polynomial. * Substitutes provided constant [argument] into [this] polynomial.
@ -149,11 +153,13 @@ public class NumberedRationalFunctionSpace<C, A: Ring<C>> (
* Substitutes provided polynomial [argument] into [this] polynomial. * Substitutes provided polynomial [argument] into [this] polynomial.
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
@JvmName("substitutePolynomial")
public inline fun NumberedPolynomial<C>.substitute(argument: Buffer<NumberedPolynomial<C>>): NumberedPolynomial<C> = substitute(ring, argument) public inline fun NumberedPolynomial<C>.substitute(argument: Buffer<NumberedPolynomial<C>>): NumberedPolynomial<C> = substitute(ring, argument)
/** /**
* Substitutes provided rational function [argument] into [this] polynomial. * Substitutes provided rational function [argument] into [this] polynomial.
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
@JvmName("substituteRationalFunction")
public inline fun NumberedPolynomial<C>.substitute(argument: Buffer<NumberedRationalFunction<C>>): NumberedRationalFunction<C> = substitute(ring, argument) public inline fun NumberedPolynomial<C>.substitute(argument: Buffer<NumberedRationalFunction<C>>): NumberedRationalFunction<C> = substitute(ring, argument)
/** /**
* Substitutes provided constant [argument] into [this] rational function. * Substitutes provided constant [argument] into [this] rational function.
@ -164,11 +170,13 @@ public class NumberedRationalFunctionSpace<C, A: Ring<C>> (
* Substitutes provided polynomial [arguments] into [this] rational function. * Substitutes provided polynomial [arguments] into [this] rational function.
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
@JvmName("substitutePolynomial")
public inline fun NumberedRationalFunction<C>.substitute(arguments: Buffer<NumberedPolynomial<C>>): NumberedRationalFunction<C> = substitute(ring, arguments) public inline fun NumberedRationalFunction<C>.substitute(arguments: Buffer<NumberedPolynomial<C>>): NumberedRationalFunction<C> = substitute(ring, arguments)
/** /**
* Substitutes provided rational function [arguments] into [this] rational function. * Substitutes provided rational function [arguments] into [this] rational function.
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
@JvmName("substituteRationalFunction")
public inline fun NumberedRationalFunction<C>.substitute(arguments: Buffer<NumberedRationalFunction<C>>): NumberedRationalFunction<C> = substitute(ring, arguments) public inline fun NumberedRationalFunction<C>.substitute(arguments: Buffer<NumberedRationalFunction<C>>): NumberedRationalFunction<C> = substitute(ring, arguments)
/** /**
* Substitutes provided constant [arguments] into [this] polynomial. * Substitutes provided constant [arguments] into [this] polynomial.
@ -222,7 +230,7 @@ public class NumberedRationalFunctionSpace<C, A: Ring<C>> (
* Substitutes provided [arguments] into [this] polynomial. * Substitutes provided [arguments] into [this] polynomial.
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
@JvmName("invokePolynomial") @JvmName("invokeRationalFunction")
public inline operator fun NumberedPolynomial<C>.invoke(arguments: Buffer<NumberedRationalFunction<C>>): NumberedRationalFunction<C> = substitute(ring, arguments) public inline operator fun NumberedPolynomial<C>.invoke(arguments: Buffer<NumberedRationalFunction<C>>): NumberedRationalFunction<C> = substitute(ring, arguments)
/** /**
* Substitutes provided [arguments] into [this] rational function. * Substitutes provided [arguments] into [this] rational function.
@ -234,6 +242,6 @@ public class NumberedRationalFunctionSpace<C, A: Ring<C>> (
* Substitutes provided [arguments] into [this] rational function. * Substitutes provided [arguments] into [this] rational function.
*/ */
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
@JvmName("invokePolynomial") @JvmName("invokeRationalFunction")
public inline operator fun NumberedRationalFunction<C>.invoke(arguments: Buffer<NumberedRationalFunction<C>>): NumberedRationalFunction<C> = substitute(ring, arguments) public inline operator fun NumberedRationalFunction<C>.invoke(arguments: Buffer<NumberedRationalFunction<C>>): NumberedRationalFunction<C> = substitute(ring, arguments)
} }

View File

@ -6,8 +6,27 @@
package space.kscience.kmath.functions 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( @RequiresOptIn(
message = "It's copy of operation with optimized boxing. It's currently unstable.", message = "It's copy of operation with optimized boxing. It's currently unstable.",
level = RequiresOptIn.Level.ERROR level = RequiresOptIn.Level.ERROR
) )
internal annotation class UnstablePolynomialBoxingOptimization 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

View File

@ -37,6 +37,38 @@ internal inline fun <C> NumberedPolynomialAsIs(pairs: Collection<Pair<List<UInt>
@PublishedApi @PublishedApi
internal inline fun <C> NumberedPolynomialAsIs(vararg pairs: Pair<List<UInt>, C>) : NumberedPolynomial<C> = NumberedPolynomial<C>(pairs.toMap()) internal inline fun <C> NumberedPolynomialAsIs(vararg pairs: Pair<List<UInt>, C>) : NumberedPolynomial<C> = NumberedPolynomial<C>(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 <C> NumberedPolynomialWithoutCheck(coefs: Map<List<UInt>, C>) : NumberedPolynomial<C> = NumberedPolynomial<C>(coefs)
/**
* Constructs [NumberedPolynomial] with provided collection of [pairs] of pairs "term's signature &mdash; 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 <C> NumberedPolynomialWithoutCheck(pairs: Collection<Pair<List<UInt>, C>>) : NumberedPolynomial<C> = NumberedPolynomial<C>(pairs.toMap())
/**
* Constructs [NumberedPolynomial] with provided array of [pairs] of pairs "term's signature &mdash; 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 <C> NumberedPolynomialWithoutCheck(vararg pairs: Pair<List<UInt>, C>) : NumberedPolynomial<C> = NumberedPolynomial<C>(pairs.toMap())
/** /**
* Constructs [NumberedPolynomial] with provided coefficients map [coefs]. * 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. * Declaring another power of the same variable will increase its degree by received degree.
*/ */
public infix fun Int.inPowerOf(deg: UInt) { public infix fun Int.inPowerOf(deg: UInt) {
if (this > signature.lastIndex) { val index = this - 1
signature.addAll(List(this - signature.lastIndex - 1) { 0u }) if (index > signature.lastIndex) {
signature.addAll(List(index - signature.lastIndex - 1) { 0u })
signature.add(deg) signature.add(deg)
} else { } else {
signature[this] += deg signature[index] += deg
} }
} }
/** /**
@ -334,22 +367,26 @@ public class NumberedPolynomialBuilder<C>(
// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available // 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. // * 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 { // * Int.algebra {
* val numberedPolynomial : NumberedPolynomial<Int> = NumberedPolynomial { // * val numberedPolynomial : NumberedPolynomial<Int> = NumberedPolynomial {
* 5 { 1 inPowerOf 2u; 3 inPowerOf 3u } // 5 x_1^2 x_3^3 + // * 5 { 1 inPowerOf 2u; 3 inPowerOf 3u } // 5 x_1^2 x_3^3 +
* (-6) { 2 inPowerOf 1u } // (-6) x_2^1 // * (-6) { 2 inPowerOf 1u } // (-6) x_2^1
* } // * }
* } // * }
* ``` // * ```
*/ // */
@UnstableKMathAPI // FIXME: For now this fabric does not let next two fabrics work. (See KT-52803.) Possible feature solutions:
@Suppress("FunctionName") // 1. `LowPriorityInOverloadResolution` becomes public. Then it should be applied to this function.
public inline fun <C, A: Ring<C>> A.NumberedPolynomial(initialCapacity: Int = 0, block: NumberedPolynomialBuilder<C>.() -> Unit) : NumberedPolynomial<C> = NumberedPolynomialBuilder(::add, initialCapacity).apply(block).build() // 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 <C, A: Ring<C>> A.NumberedPolynomial(initialCapacity: Int = 0, block: NumberedPolynomialBuilder<C>.() -> Unit) : NumberedPolynomial<C> = NumberedPolynomialBuilder(::add, initialCapacity).apply(block).build()
/** /**
* Creates [NumberedPolynomial] with lambda [block] in context of [this] ring of [NumberedPolynomial]s. * Creates [NumberedPolynomial] with lambda [block] in context of [this] ring of [NumberedPolynomial]s.
* *
@ -365,7 +402,7 @@ public inline fun <C, A: Ring<C>> A.NumberedPolynomial(initialCapacity: Int = 0,
*/ */
@UnstableKMathAPI @UnstableKMathAPI
@Suppress("FunctionName") @Suppress("FunctionName")
public inline fun <C, A: Ring<C>> NumberedPolynomialSpace<C, A>.NumberedPolynomial(initialCapacity: Int, block: NumberedPolynomialBuilder<C>.() -> Unit) : NumberedPolynomial<C> = NumberedPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build() public inline fun <C, A: Ring<C>> NumberedPolynomialSpace<C, A>.NumberedPolynomial(initialCapacity: Int = 0, block: NumberedPolynomialBuilder<C>.() -> Unit) : NumberedPolynomial<C> = NumberedPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build()
/** /**
* Creates [NumberedPolynomial] with lambda [block] in context of [this] field of [NumberedRationalFunction]s. * Creates [NumberedPolynomial] with lambda [block] in context of [this] field of [NumberedRationalFunction]s.
* *
@ -381,7 +418,7 @@ public inline fun <C, A: Ring<C>> NumberedPolynomialSpace<C, A>.NumberedPolynomi
*/ */
@UnstableKMathAPI @UnstableKMathAPI
@Suppress("FunctionName") @Suppress("FunctionName")
public inline fun <C, A: Ring<C>> NumberedRationalFunctionSpace<C, A>.NumberedPolynomial(initialCapacity: Int, block: NumberedPolynomialBuilder<C>.() -> Unit) : NumberedPolynomial<C> = NumberedPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build() public inline fun <C, A: Ring<C>> NumberedRationalFunctionSpace<C, A>.NumberedPolynomial(initialCapacity: Int = 0, block: NumberedPolynomialBuilder<C>.() -> Unit) : NumberedPolynomial<C> = 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 // Waiting for context receivers :( FIXME: Replace with context receivers when they will be available

View File

@ -86,7 +86,7 @@ public fun <C> NumberedPolynomial<C>.substitute(ring: Ring<C>, args: Map<Int, C>
/** /**
* Substitutes provided arguments [args] into [this] polynomial. * Substitutes provided arguments [args] into [this] polynomial.
*/ // TODO: To optimize boxing */ // TODO: To optimize boxing
@JvmName("substitutePolynomial") @JvmName("substitutePolynomial")
public fun <C> NumberedPolynomial<C>.substitute(ring: Ring<C>, args: Map<Int, NumberedPolynomial<C>>) : NumberedPolynomial<C> = public fun <C> NumberedPolynomial<C>.substitute(ring: Ring<C>, args: Map<Int, NumberedPolynomial<C>>) : NumberedPolynomial<C> =
ring.numberedPolynomialSpace { ring.numberedPolynomialSpace {

View File

@ -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. * 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 package space.kscience.kmath.functions
import space.kscience.kmath.test.misc.* import space.kscience.kmath.test.misc.*
@ -28,25 +30,32 @@ class ListPolynomialTest {
ListPolynomial(Rational(-2)) + 2, ListPolynomial(Rational(-2)) + 2,
"test 3" "test 3"
) )
assertEquals( val polynomial_4 = ListPolynomial<Rational>()
ListPolynomial(), assertSame(
ListPolynomial<Rational>() + 0, polynomial_4,
polynomial_4 + 0,
"test 4" "test 4"
) )
val polynomial_5 = ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7))
assertSame(
polynomial_5,
polynomial_5 + 0,
"test 5"
)
assertEquals( assertEquals(
ListPolynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), ListPolynomial(Rational(-1), Rational(0), Rational(0), Rational(0)),
ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + 1, ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + 1,
"test 5" "test 6"
) )
assertEquals( assertEquals(
ListPolynomial(Rational(-1)), ListPolynomial(Rational(-1)),
ListPolynomial(Rational(-2)) + 1, ListPolynomial(Rational(-2)) + 1,
"test 6" "test 7"
) )
assertEquals( assertEquals(
ListPolynomial(Rational(2)), ListPolynomial(Rational(2)),
ListPolynomial<Rational>() + 2, ListPolynomial<Rational>() + 2,
"test 7" "test 8"
) )
} }
} }
@ -68,25 +77,32 @@ class ListPolynomialTest {
ListPolynomial(Rational(2)) - 2, ListPolynomial(Rational(2)) - 2,
"test 3" "test 3"
) )
assertEquals( val polynomial_4 = ListPolynomial<Rational>()
ListPolynomial(), assertSame(
ListPolynomial<Rational>() - 0, polynomial_4,
polynomial_4 - 0,
"test 4" "test 4"
) )
val polynomial_5 = ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7))
assertEquals(
polynomial_5,
polynomial_5 - 0,
"test 5"
)
assertEquals( assertEquals(
ListPolynomial(Rational(1), Rational(0), Rational(0), Rational(0)), ListPolynomial(Rational(1), Rational(0), Rational(0), Rational(0)),
ListPolynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - 1, ListPolynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - 1,
"test 5" "test 6"
) )
assertEquals( assertEquals(
ListPolynomial(Rational(1)), ListPolynomial(Rational(1)),
ListPolynomial(Rational(2)) - 1, ListPolynomial(Rational(2)) - 1,
"test 6" "test 7"
) )
assertEquals( assertEquals(
ListPolynomial(Rational(-2)), ListPolynomial(Rational(-2)),
ListPolynomial<Rational>() - 2, ListPolynomial<Rational>() - 2,
"test 7" "test 8"
) )
} }
} }
@ -103,6 +119,17 @@ class ListPolynomialTest {
ListPolynomial(7, 0, 49, 21, 14) * 15, ListPolynomial(7, 0, 49, 21, 14) * 15,
"test 2" "test 2"
) )
val polynomial = ListPolynomial(22, 26, 13, 15, 26)
assertSame(
zero,
polynomial * 0,
"test 3"
)
assertSame(
polynomial,
polynomial * 1,
"test 4"
)
} }
} }
@Test @Test
@ -123,25 +150,32 @@ class ListPolynomialTest {
2 + ListPolynomial(Rational(-2)), 2 + ListPolynomial(Rational(-2)),
"test 3" "test 3"
) )
assertEquals( val polynomial_4 = ListPolynomial<Rational>()
ListPolynomial(), assertSame(
0 + ListPolynomial(), polynomial_4,
0 + polynomial_4,
"test 4" "test 4"
) )
val polynomial_5 = ListPolynomial<Rational>(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7))
assertSame(
polynomial_5,
0 + polynomial_5,
"test 5"
)
assertEquals( assertEquals(
ListPolynomial(Rational(-1), Rational(0), Rational(0), Rational(0)), ListPolynomial(Rational(-1), Rational(0), Rational(0), Rational(0)),
1 + ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), 1 + ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)),
"test 5" "test 6"
) )
assertEquals( assertEquals(
ListPolynomial(Rational(-1)), ListPolynomial(Rational(-1)),
1 + ListPolynomial(Rational(-2)), 1 + ListPolynomial(Rational(-2)),
"test 6" "test 7"
) )
assertEquals( assertEquals(
ListPolynomial(Rational(2)), ListPolynomial(Rational(2)),
2 + ListPolynomial(), 2 + ListPolynomial(),
"test 7" "test 8"
) )
} }
} }
@ -163,25 +197,30 @@ class ListPolynomialTest {
-2 - ListPolynomial(Rational(-2)), -2 - ListPolynomial(Rational(-2)),
"test 3" "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( assertEquals(
ListPolynomial(), ListPolynomial(),
0 - ListPolynomial(), 0 - ListPolynomial(),
"test 4" "test 5"
) )
assertEquals( assertEquals(
ListPolynomial(Rational(1), Rational(0), Rational(0), Rational(0)), ListPolynomial(Rational(1), Rational(0), Rational(0), Rational(0)),
-1 - ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)), -1 - ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)),
"test 5" "test 6"
) )
assertEquals( assertEquals(
ListPolynomial(Rational(1)), ListPolynomial(Rational(1)),
-1 - ListPolynomial(Rational(-2)), -1 - ListPolynomial(Rational(-2)),
"test 6" "test 7"
) )
assertEquals( assertEquals(
ListPolynomial(Rational(-2)), ListPolynomial(Rational(-2)),
-2 - ListPolynomial(), -2 - ListPolynomial(),
"test 7" "test 8"
) )
} }
} }
@ -198,6 +237,17 @@ class ListPolynomialTest {
15 * ListPolynomial(7, 0, 49, 21, 14), 15 * ListPolynomial(7, 0, 49, 21, 14),
"test 2" "test 2"
) )
val polynomial = ListPolynomial(22, 26, 13, 15, 26)
assertSame(
zero,
0 * polynomial,
"test 3"
)
assertSame(
polynomial,
1 * polynomial,
"test 4"
)
} }
} }
@Test @Test

View File

@ -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<UInt>() 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<UInt>() to -1,
),
Int.algebra {
NumberedPolynomial(
listOf(0u) to 5,
listOf(0u, 0u) to -6,
)
},
"test 3"
)
assertEquals(
NumberedPolynomialAsIs(
listOf<UInt>() to 0,
),
Int.algebra {
NumberedPolynomial(
listOf(0u) to 5,
listOf(0u, 0u) to -5,
)
},
"test 4"
)
}
}

View File

@ -7,6 +7,7 @@ package space.kscience.kmath.test.misc
import space.kscience.kmath.functions.ListPolynomial import space.kscience.kmath.functions.ListPolynomial
import space.kscience.kmath.functions.ListPolynomialSpace import space.kscience.kmath.functions.ListPolynomialSpace
import space.kscience.kmath.functions.PolynomialSpaceOverRing
import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.Ring
@ -136,3 +137,6 @@ fun ListPolynomialSpace<IntModulo, IntModuloRing>.ListPolynomial(vararg coefs: I
ListPolynomial(coefs.map { IntModulo(it, ring.modulus) }) ListPolynomial(coefs.map { IntModulo(it, ring.modulus) })
fun IntModuloRing.ListPolynomial(vararg coefs: Int): ListPolynomial<IntModulo> = fun IntModuloRing.ListPolynomial(vararg coefs: Int): ListPolynomial<IntModulo> =
ListPolynomial(coefs.map { IntModulo(it, modulus) }) ListPolynomial(coefs.map { IntModulo(it, modulus) })
fun IntModuloRing.m(arg: Int) = IntModulo(arg, modulus)
fun PolynomialSpaceOverRing<IntModulo, *, IntModuloRing>.m(arg: Int) = IntModulo(arg, ring.modulus)