Feature: Polynomials and rational functions #469
@ -87,7 +87,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
||||
)
|
||||
else LabeledPolynomialAsIs(
|
||||
mapOf(this@plus to 1U) to constantOne,
|
||||
emptyMap<Symbol, UInt>() to constantOne * other,
|
||||
emptyMap<Symbol, UInt>() 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<C, A : Ring<C>>(
|
||||
)
|
||||
else LabeledPolynomialAsIs(
|
||||
mapOf(this@minus to 1U) to constantOne,
|
||||
emptyMap<Symbol, UInt>() to constantOne * -other,
|
||||
emptyMap<Symbol, UInt>() 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<C, A : Ring<C>>(
|
||||
public override operator fun Symbol.times(other: Int): LabeledPolynomial<C> =
|
||||
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<C, A : Ring<C>>(
|
||||
)
|
||||
else LabeledPolynomialAsIs(
|
||||
mapOf(other to 1U) to constantOne,
|
||||
emptyMap<Symbol, UInt>() to constantOne * this@plus,
|
||||
emptyMap<Symbol, UInt>() 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<C, A : Ring<C>>(
|
||||
public override operator fun Int.times(other: Symbol): LabeledPolynomial<C> =
|
||||
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<C, A : Ring<C>>(
|
||||
* The operation is equivalent to adding [other] copies of unit polynomial to [this].
|
||||
*/
|
||||
public override operator fun LabeledPolynomial<C>.plus(other: Int): LabeledPolynomial<C> =
|
||||
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<C, A : Ring<C>>(
|
||||
* The operation is equivalent to subtraction [other] copies of unit polynomial from [this].
|
||||
*/
|
||||
public override operator fun LabeledPolynomial<C>.minus(other: Int): LabeledPolynomial<C> =
|
||||
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<C, A : Ring<C>>(
|
||||
* The operation is equivalent to adding [this] copies of unit polynomial to [other].
|
||||
*/
|
||||
public override operator fun Int.plus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||
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<C, A : Ring<C>>(
|
||||
* Returns sum of the constant represented as a polynomial and the polynomial.
|
||||
*/
|
||||
override operator fun C.plus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||
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<C, A : Ring<C>>(
|
||||
* Returns sum of the constant represented as a polynomial and the polynomial.
|
||||
*/
|
||||
override operator fun LabeledPolynomial<C>.plus(other: C): LabeledPolynomial<C> =
|
||||
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<C>.minus(other: C): LabeledPolynomial<C> =
|
||||
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<C, A : Ring<C>>(
|
||||
* Returns sum of the variable represented as a monic monomial and the polynomial.
|
||||
*/
|
||||
public override operator fun Symbol.plus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||
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<C, A : Ring<C>>(
|
||||
* Returns sum of the polynomial and the variable represented as a monic monomial.
|
||||
*/
|
||||
public override operator fun LabeledPolynomial<C>.plus(other: Symbol): LabeledPolynomial<C> =
|
||||
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<C>.minus(other: Symbol): LabeledPolynomial<C> =
|
||||
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.
|
||||
*/
|
||||
|
@ -69,10 +69,9 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
||||
*/
|
||||
public override operator fun NumberedPolynomial<C>.plus(other: Int): NumberedPolynomial<C> =
|
||||
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<C, A : Ring<C>>(
|
||||
*/
|
||||
public override operator fun NumberedPolynomial<C>.minus(other: Int): NumberedPolynomial<C> =
|
||||
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<C, A : Ring<C>>(
|
||||
*/
|
||||
public override operator fun Int.plus(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
||||
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<C>): NumberedPolynomial<C> =
|
||||
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<UInt>()
|
||||
|
||||
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<C, A : Ring<C>>(
|
||||
* Returns sum of the constant represented as a polynomial and the polynomial.
|
||||
*/
|
||||
override operator fun C.plus(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
||||
with(other.coefficients) {
|
||||
if (isEmpty()) NumberedPolynomialAsIs(mapOf(emptyList<UInt>() 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<C>): NumberedPolynomial<C> =
|
||||
with(other.coefficients) {
|
||||
if (isEmpty()) NumberedPolynomialAsIs(mapOf(emptyList<UInt>() to this@minus))
|
||||
else NumberedPolynomialAsIs(
|
||||
toMutableMap()
|
||||
.apply {
|
||||
forEach { (degs, c) -> if (degs.isNotEmpty()) this[degs] = -c }
|
||||
|
||||
val degs = emptyList<UInt>()
|
||||
|
||||
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<C, A : Ring<C>>(
|
||||
* Returns sum of the constant represented as a polynomial and the polynomial.
|
||||
*/
|
||||
override operator fun NumberedPolynomial<C>.plus(other: C): NumberedPolynomial<C> =
|
||||
with(coefficients) {
|
||||
if (isEmpty()) NumberedPolynomialAsIs(mapOf(emptyList<UInt>() 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<C>.minus(other: C): NumberedPolynomial<C> =
|
||||
with(coefficients) {
|
||||
if (isEmpty()) NumberedPolynomialAsIs(mapOf(emptyList<UInt>() 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<C, A : Ring<C>>(
|
||||
/**
|
||||
* Instance of unit polynomial (unit of the polynomial ring).
|
||||
*/
|
||||
override val one: NumberedPolynomial<C> by lazy {
|
||||
NumberedPolynomialAsIs(
|
||||
mapOf(
|
||||
emptyList<UInt>() to constantOne // 1 * x_1^0 * x_2^0 * ...
|
||||
)
|
||||
)
|
||||
}
|
||||
override val one: NumberedPolynomial<C> by lazy { NumberedPolynomialAsIs(mapOf(emptyList<UInt>() to constantOne)) }
|
||||
|
||||
/**
|
||||
* Maximal index (ID) of variable occurring in the polynomial with positive power. If there is no such variable,
|
||||
|
@ -9,6 +9,40 @@ import kotlin.contracts.InvocationKind.*
|
||||
import kotlin.contracts.contract
|
||||
|
||||
|
||||
// TODO: Docs
|
||||
internal inline fun <K, V, R> Map<in K, V>.computeOn(key: K, compute: (V?) -> R): R {
|
||||
contract {
|
||||
callsInPlace(compute, EXACTLY_ONCE)
|
||||
}
|
||||
return compute(get(key))
|
||||
}
|
||||
|
||||
// TODO: Docs
|
||||
internal inline fun <K, V, R> Map<K, V>.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 <K, V, R> Map<K, V>.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 <K, V, R> Map<K, V>.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 <K, V> MutableMap<in K, V>.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 <K, V> MutableMap<K, V>.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 }
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user