Feature: Polynomials and rational functions #469
@ -58,6 +58,8 @@ internal fun Map<Symbol, UInt>.cleanUp() = filterValues { it > 0U }
|
||||
|
||||
@Suppress("FunctionName", "NOTHING_TO_INLINE")
|
||||
internal inline fun <C, A: Ring<C>> LabeledPolynomialSpace<C, A>.LabeledPolynomial(coefs: Map<Map<Symbol, UInt>, C>, toCheckInput: Boolean = true) : LabeledPolynomial<C> = ring.LabeledPolynomial(coefs, toCheckInput)
|
||||
@Suppress("FunctionName", "NOTHING_TO_INLINE")
|
||||
internal inline fun <C, A: Ring<C>> LabeledRationalFunctionSpace<C, A>.LabeledPolynomial(coefs: Map<Map<Symbol, UInt>, C>, toCheckInput: Boolean = true) : LabeledPolynomial<C> = ring.LabeledPolynomial(coefs, toCheckInput)
|
||||
@Suppress("FunctionName")
|
||||
internal fun <C, A: Ring<C>> A.LabeledPolynomial(coefs: Map<Map<Symbol, UInt>, C>, toCheckInput: Boolean = true) : LabeledPolynomial<C> {
|
||||
if (!toCheckInput) return LabeledPolynomial<C>(coefs)
|
||||
@ -70,13 +72,13 @@ internal fun <C, A: Ring<C>> A.LabeledPolynomial(coefs: Map<Map<Symbol, UInt>, C
|
||||
fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value
|
||||
}
|
||||
|
||||
return LabeledPolynomial<C>(
|
||||
fixedCoefs.filterValues { it != zero }
|
||||
)
|
||||
return LabeledPolynomial<C>(fixedCoefs)
|
||||
}
|
||||
|
||||
@Suppress("FunctionName", "NOTHING_TO_INLINE")
|
||||
internal inline fun <C, A: Ring<C>> LabeledPolynomialSpace<C, A>.LabeledPolynomial(pairs: Collection<Pair<Map<Symbol, UInt>, C>>, toCheckInput: Boolean = true) : LabeledPolynomial<C> = ring.LabeledPolynomial(pairs, toCheckInput)
|
||||
@Suppress("FunctionName", "NOTHING_TO_INLINE")
|
||||
internal inline fun <C, A: Ring<C>> LabeledRationalFunctionSpace<C, A>.LabeledPolynomial(pairs: Collection<Pair<Map<Symbol, UInt>, C>>, toCheckInput: Boolean = true) : LabeledPolynomial<C> = ring.LabeledPolynomial(pairs, toCheckInput)
|
||||
@Suppress("FunctionName")
|
||||
internal fun <C, A: Ring<C>> A.LabeledPolynomial(pairs: Collection<Pair<Map<Symbol, UInt>, C>>, toCheckInput: Boolean = true) : LabeledPolynomial<C> {
|
||||
if (!toCheckInput) return LabeledPolynomial<C>(pairs.toMap())
|
||||
@ -89,13 +91,13 @@ internal fun <C, A: Ring<C>> A.LabeledPolynomial(pairs: Collection<Pair<Map<Symb
|
||||
fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value
|
||||
}
|
||||
|
||||
return LabeledPolynomial<C>(
|
||||
fixedCoefs.filterValues { it != zero }
|
||||
)
|
||||
return LabeledPolynomial<C>(fixedCoefs)
|
||||
}
|
||||
|
||||
@Suppress("FunctionName", "NOTHING_TO_INLINE")
|
||||
internal inline fun <C, A: Ring<C>> LabeledPolynomialSpace<C, A>.LabeledPolynomial(vararg pairs: Pair<Map<Symbol, UInt>, C>, toCheckInput: Boolean = true) : LabeledPolynomial<C> = ring.LabeledPolynomial(pairs = pairs, toCheckInput = toCheckInput)
|
||||
@Suppress("FunctionName", "NOTHING_TO_INLINE")
|
||||
internal inline fun <C, A: Ring<C>> LabeledRationalFunctionSpace<C, A>.LabeledPolynomial(vararg pairs: Pair<Map<Symbol, UInt>, C>, toCheckInput: Boolean = true) : LabeledPolynomial<C> = ring.LabeledPolynomial(pairs = pairs, toCheckInput = toCheckInput)
|
||||
@Suppress("FunctionName")
|
||||
internal fun <C, A: Ring<C>> A.LabeledPolynomial(vararg pairs: Pair<Map<Symbol, UInt>, C>, toCheckInput: Boolean = true) : LabeledPolynomial<C> {
|
||||
if (!toCheckInput) return LabeledPolynomial<C>(pairs.toMap())
|
||||
@ -108,25 +110,29 @@ internal fun <C, A: Ring<C>> A.LabeledPolynomial(vararg pairs: Pair<Map<Symbol,
|
||||
fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value
|
||||
}
|
||||
|
||||
return LabeledPolynomial<C>(
|
||||
fixedCoefs.filterValues { it != zero }
|
||||
)
|
||||
return LabeledPolynomial<C>(fixedCoefs)
|
||||
}
|
||||
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> A.LabeledPolynomial(coefs: Map<Map<Symbol, UInt>, C>) : LabeledPolynomial<C> = LabeledPolynomial(coefs, toCheckInput = true)
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> LabeledPolynomialSpace<C, A>.LabeledPolynomial(coefs: Map<Map<Symbol, UInt>, C>) : LabeledPolynomial<C> = LabeledPolynomial(coefs, toCheckInput = true)
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> LabeledRationalFunctionSpace<C, A>.LabeledPolynomial(coefs: Map<Map<Symbol, UInt>, C>) : LabeledPolynomial<C> = LabeledPolynomial(coefs, toCheckInput = true)
|
||||
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> A.LabeledPolynomial(pairs: Collection<Pair<Map<Symbol, UInt>, C>>) : LabeledPolynomial<C> = LabeledPolynomial(pairs, toCheckInput = true)
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> LabeledPolynomialSpace<C, A>.LabeledPolynomial(pairs: Collection<Pair<Map<Symbol, UInt>, C>>) : LabeledPolynomial<C> = LabeledPolynomial(pairs, toCheckInput = true)
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> LabeledRationalFunctionSpace<C, A>.LabeledPolynomial(pairs: Collection<Pair<Map<Symbol, UInt>, C>>) : LabeledPolynomial<C> = LabeledPolynomial(pairs, toCheckInput = true)
|
||||
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> A.LabeledPolynomial(vararg pairs: Pair<Map<Symbol, UInt>, C>) : LabeledPolynomial<C> = LabeledPolynomial(*pairs, toCheckInput = true)
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> LabeledPolynomialSpace<C, A>.LabeledPolynomial(vararg pairs: Pair<Map<Symbol, UInt>, C>) : LabeledPolynomial<C> = LabeledPolynomial(*pairs, toCheckInput = true)
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> LabeledRationalFunctionSpace<C, A>.LabeledPolynomial(vararg pairs: Pair<Map<Symbol, UInt>, C>) : LabeledPolynomial<C> = LabeledPolynomial(*pairs, toCheckInput = true)
|
||||
|
||||
//context(A)
|
||||
//public fun <C, A: Ring<C>> Symbol.asLabeledPolynomial() : LabeledPolynomial<C> = LabeledPolynomial<C>(mapOf(mapOf(this to 1u) to one))
|
||||
@ -196,19 +202,17 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
||||
*/
|
||||
public override operator fun LabeledPolynomial<C>.plus(other: Int): LabeledPolynomial<C> =
|
||||
if (other == 0) this
|
||||
else
|
||||
LabeledPolynomial(
|
||||
coefficients
|
||||
.toMutableMap()
|
||||
else with(coefficients) {
|
||||
if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to other.asConstant()))
|
||||
else LabeledPolynomial<C>(
|
||||
toMutableMap()
|
||||
.apply {
|
||||
val degs = emptyMap<Symbol, UInt>()
|
||||
|
||||
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<C, A : Ring<C>>(
|
||||
*/
|
||||
public override operator fun LabeledPolynomial<C>.minus(other: Int): LabeledPolynomial<C> =
|
||||
if (other == 0) this
|
||||
else
|
||||
LabeledPolynomial(
|
||||
coefficients
|
||||
.toMutableMap()
|
||||
else with(coefficients) {
|
||||
if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to (-other).asConstant()))
|
||||
else LabeledPolynomial<C>(
|
||||
toMutableMap()
|
||||
.apply {
|
||||
val degs = emptyMap<Symbol, UInt>()
|
||||
|
||||
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<C, A : Ring<C>>(
|
||||
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<C, A : Ring<C>>(
|
||||
*/
|
||||
public override operator fun Int.plus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||
if (this == 0) other
|
||||
else
|
||||
LabeledPolynomial(
|
||||
other.coefficients
|
||||
.toMutableMap()
|
||||
else with(other.coefficients) {
|
||||
if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to this@plus.asConstant()))
|
||||
else LabeledPolynomial<C>(
|
||||
toMutableMap()
|
||||
.apply {
|
||||
val degs = emptyMap<Symbol, UInt>()
|
||||
|
||||
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<C, A : Ring<C>>(
|
||||
*/
|
||||
public override operator fun Int.minus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||
if (this == 0) other
|
||||
else
|
||||
LabeledPolynomial(
|
||||
other.coefficients
|
||||
.toMutableMap()
|
||||
else with(other.coefficients) {
|
||||
if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to this@minus.asConstant()))
|
||||
else LabeledPolynomial<C>(
|
||||
toMutableMap()
|
||||
.apply {
|
||||
val degs = emptyMap<Symbol, UInt>()
|
||||
|
||||
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<C, A : Ring<C>>(
|
||||
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<C, A : Ring<C>>(
|
||||
public override fun number(value: Int): LabeledPolynomial<C> = number(constantNumber(value))
|
||||
|
||||
public override operator fun C.plus(other: Symbol): LabeledPolynomial<C> =
|
||||
if (isZero()) LabeledPolynomial<C>(mapOf(
|
||||
mapOf(other to 1U) to constantOne,
|
||||
))
|
||||
else LabeledPolynomial<C>(mapOf(
|
||||
LabeledPolynomial<C>(mapOf(
|
||||
mapOf(other to 1U) to constantOne,
|
||||
emptyMap<Symbol, UInt>() to this@plus,
|
||||
))
|
||||
public override operator fun C.minus(other: Symbol): LabeledPolynomial<C> =
|
||||
if (isZero()) LabeledPolynomial<C>(mapOf(
|
||||
mapOf(other to 1U) to -constantOne,
|
||||
))
|
||||
else LabeledPolynomial<C>(mapOf(
|
||||
LabeledPolynomial<C>(mapOf(
|
||||
mapOf(other to 1U) to -constantOne,
|
||||
emptyMap<Symbol, UInt>() to this@minus,
|
||||
))
|
||||
public override operator fun C.times(other: Symbol): LabeledPolynomial<C> =
|
||||
if (isZero()) zero
|
||||
else LabeledPolynomial<C>(mapOf(
|
||||
LabeledPolynomial<C>(mapOf(
|
||||
mapOf(other to 1U) to this@times,
|
||||
))
|
||||
|
||||
public override operator fun Symbol.plus(other: C): LabeledPolynomial<C> =
|
||||
if (other.isZero()) LabeledPolynomial<C>(mapOf(
|
||||
mapOf(this@plus to 1U) to constantOne,
|
||||
))
|
||||
else LabeledPolynomial<C>(mapOf(
|
||||
LabeledPolynomial<C>(mapOf(
|
||||
mapOf(this@plus to 1U) to constantOne,
|
||||
emptyMap<Symbol, UInt>() to other,
|
||||
))
|
||||
public override operator fun Symbol.minus(other: C): LabeledPolynomial<C> =
|
||||
if (other.isZero()) LabeledPolynomial<C>(mapOf(
|
||||
mapOf(this@minus to 1U) to -constantOne,
|
||||
))
|
||||
else LabeledPolynomial<C>(mapOf(
|
||||
LabeledPolynomial<C>(mapOf(
|
||||
mapOf(this@minus to 1U) to -constantOne,
|
||||
emptyMap<Symbol, UInt>() to other,
|
||||
))
|
||||
public override operator fun Symbol.times(other: C): LabeledPolynomial<C> =
|
||||
if (other.isZero()) zero
|
||||
else LabeledPolynomial<C>(mapOf(
|
||||
LabeledPolynomial<C>(mapOf(
|
||||
mapOf(this@times to 1U) to other,
|
||||
))
|
||||
|
||||
@ -350,18 +336,14 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
||||
* Returns sum of the constant represented as polynomial and the polynomial.
|
||||
*/
|
||||
override operator fun C.plus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||
if (this.isZero()) other
|
||||
else with(other.coefficients) {
|
||||
with(other.coefficients) {
|
||||
if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to this@plus))
|
||||
else LabeledPolynomial<C>(
|
||||
toMutableMap()
|
||||
.apply {
|
||||
val degs = emptyMap<Symbol, UInt>()
|
||||
|
||||
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<C, A : Ring<C>>(
|
||||
* Returns difference between the constant represented as polynomial and the polynomial.
|
||||
*/
|
||||
override operator fun C.minus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||
if (this.isZero()) other
|
||||
else with(other.coefficients) {
|
||||
with(other.coefficients) {
|
||||
if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to this@minus))
|
||||
else LabeledPolynomial<C>(
|
||||
toMutableMap()
|
||||
@ -379,10 +360,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
||||
|
||||
val degs = emptyMap<Symbol, UInt>()
|
||||
|
||||
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<C, A : Ring<C>>(
|
||||
* Returns product of the constant represented as polynomial and the polynomial.
|
||||
*/
|
||||
override operator fun C.times(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||
if (this.isZero()) zero
|
||||
else LabeledPolynomial<C>(
|
||||
LabeledPolynomial<C>(
|
||||
other.coefficients
|
||||
.applyAndRemoveZeros {
|
||||
.toMutableMap()
|
||||
.apply {
|
||||
for (degs in keys) this[degs] = this@times * this[degs]!!
|
||||
}
|
||||
)
|
||||
@ -402,18 +380,14 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
||||
* Returns sum of the constant represented as polynomial and the polynomial.
|
||||
*/
|
||||
override operator fun LabeledPolynomial<C>.plus(other: C): LabeledPolynomial<C> =
|
||||
if (other.isZero()) this
|
||||
else with(coefficients) {
|
||||
with(coefficients) {
|
||||
if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to other))
|
||||
else LabeledPolynomial<C>(
|
||||
toMutableMap()
|
||||
.apply {
|
||||
val degs = emptyMap<Symbol, UInt>()
|
||||
|
||||
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<C, A : Ring<C>>(
|
||||
* Returns difference between the constant represented as polynomial and the polynomial.
|
||||
*/
|
||||
override operator fun LabeledPolynomial<C>.minus(other: C): LabeledPolynomial<C> =
|
||||
if (other.isZero()) this
|
||||
else with(coefficients) {
|
||||
with(coefficients) {
|
||||
if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to other))
|
||||
else LabeledPolynomial<C>(
|
||||
toMutableMap()
|
||||
@ -431,10 +404,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
||||
|
||||
val degs = emptyMap<Symbol, UInt>()
|
||||
|
||||
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<C, A : Ring<C>>(
|
||||
* Returns product of the constant represented as polynomial and the polynomial.
|
||||
*/
|
||||
override operator fun LabeledPolynomial<C>.times(other: C): LabeledPolynomial<C> =
|
||||
if (other.isZero()) zero
|
||||
else LabeledPolynomial<C>(
|
||||
LabeledPolynomial<C>(
|
||||
coefficients
|
||||
.applyAndRemoveZeros {
|
||||
.toMutableMap()
|
||||
.apply {
|
||||
for (degs in keys) this[degs] = this[degs]!! * other
|
||||
}
|
||||
)
|
||||
@ -454,8 +424,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
||||
* Converts the constant [value] to polynomial.
|
||||
*/
|
||||
public override fun number(value: C): LabeledPolynomial<C> =
|
||||
if (value == 0) zero
|
||||
else LabeledPolynomial(mapOf(emptyMap<Symbol, UInt>() to value))
|
||||
LabeledPolynomial(mapOf(emptyMap<Symbol, UInt>() to value))
|
||||
|
||||
public override operator fun Symbol.unaryPlus(): LabeledPolynomial<C> =
|
||||
LabeledPolynomial<C>(mapOf(
|
||||
@ -495,10 +464,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
||||
.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<C, A : Ring<C>>(
|
||||
|
||||
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<C, A : Ring<C>>(
|
||||
.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<C, A : Ring<C>>(
|
||||
.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<C, A : Ring<C>>(
|
||||
*/
|
||||
override operator fun LabeledPolynomial<C>.plus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||
LabeledPolynomial<C>(
|
||||
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<C, A : Ring<C>>(
|
||||
*/
|
||||
override operator fun LabeledPolynomial<C>.minus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||
LabeledPolynomial<C>(
|
||||
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,11 +549,8 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
||||
* Returns product of the polynomials.
|
||||
*/
|
||||
override operator fun LabeledPolynomial<C>.times(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||
when {
|
||||
isZero() -> zero
|
||||
other.isZero() -> zero
|
||||
else -> LabeledPolynomial<C>(
|
||||
buildCoefficients(coefficients.size * other.coefficients.size) {
|
||||
LabeledPolynomial<C>(
|
||||
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 }
|
||||
@ -605,7 +559,6 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Instance of zero polynomial (zero of the polynomial ring).
|
||||
@ -616,22 +569,12 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
||||
*/
|
||||
override val one: LabeledPolynomial<C> = LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to constantOne))
|
||||
|
||||
/**
|
||||
* Checks equality of the polynomials.
|
||||
*/
|
||||
override infix fun LabeledPolynomial<C>.equalsTo(other: LabeledPolynomial<C>): 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<C>.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<C, A : Ring<C>>(
|
||||
public override val LabeledPolynomial<C>.degrees: Map<Symbol, UInt>
|
||||
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<C, A : Ring<C>>(
|
||||
* Counts degree of the polynomial by the specified [variable].
|
||||
*/
|
||||
public override fun LabeledPolynomial<C>.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<C>.degreeBy(variables: Collection<Symbol>): 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<C>.variables: Set<Symbol>
|
||||
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<C>.countOfVariables: Int get() = variables.size
|
||||
|
||||
/**
|
||||
* Checks if the instant is constant polynomial (of degree no more than 0) over considered ring.
|
||||
*/
|
||||
override fun LabeledPolynomial<C>.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<C>.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<C>.asConstantOrNull(): C? =
|
||||
with(coefficients) {
|
||||
if(isConstant()) getOrElse(emptyMap()) { constantZero }
|
||||
else null
|
||||
}
|
||||
|
||||
// @Suppress("NOTHING_TO_INLINE")
|
||||
// public inline fun LabeledPolynomial<C>.substitute(argument: Map<Symbol, C>): LabeledPolynomial<C> = this.substitute(ring, argument)
|
||||
// @Suppress("NOTHING_TO_INLINE")
|
||||
@ -719,33 +632,4 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
||||
// @Suppress("NOTHING_TO_INLINE")
|
||||
// @JvmName("invokePolynomial")
|
||||
// public inline operator fun LabeledPolynomial<C>.invoke(argument: Map<Symbol, LabeledPolynomial<C>>): LabeledPolynomial<C> = this.substitute(ring, argument)
|
||||
|
||||
// TODO: Move to other internal utilities with context receiver
|
||||
@JvmName("applyAndRemoveZerosInternal")
|
||||
internal fun MutableMap<Map<Symbol, UInt>, C>.applyAndRemoveZeros(block: MutableMap<Map<Symbol, UInt>, C>.() -> Unit) : MutableMap<Map<Symbol, UInt>, C> {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
block()
|
||||
for ((degs, c) in this) if (c.isZero()) this.remove(degs)
|
||||
return this
|
||||
}
|
||||
internal fun Map<Map<Symbol, UInt>, C>.applyAndRemoveZeros(block: MutableMap<Map<Symbol, UInt>, C>.() -> Unit) : Map<Map<Symbol, UInt>, C> =
|
||||
toMutableMap().applyAndRemoveZeros(block)
|
||||
@OptIn(ExperimentalTypeInference::class)
|
||||
internal inline fun buildCoefficients(@BuilderInference builderAction: MutableMap<Map<Symbol, UInt>, C>.() -> Unit): Map<Map<Symbol, UInt>, 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<Map<Symbol, UInt>, C>.() -> Unit): Map<Map<Symbol, UInt>, C> {
|
||||
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
|
||||
return buildMap(capacity) {
|
||||
builderAction()
|
||||
for ((degs, c) in this) if (c.isZero()) this.remove(degs)
|
||||
}
|
||||
}
|
||||
}
|
@ -19,45 +19,35 @@ public class LabeledRationalFunction<C>(
|
||||
|
||||
// Waiting for context receivers :( TODO: Replace with context receivers when they will be available
|
||||
|
||||
@Suppress("FunctionName")
|
||||
internal fun <C, A: Ring<C>> LabeledRationalFunctionSpace<C, A>.LabeledRationalFunction(numerator: LabeledPolynomial<C>, denominator: LabeledPolynomial<C>): LabeledRationalFunction<C> =
|
||||
if (denominator.isZero()) throw ArithmeticException("/ by zero")
|
||||
else LabeledRationalFunction<C>(numerator, denominator)
|
||||
@Suppress("FunctionName")
|
||||
internal fun <C, A: Ring<C>> A.LabeledRationalFunction(numerator: LabeledPolynomial<C>, denominator: LabeledPolynomial<C>): LabeledRationalFunction<C> =
|
||||
if (denominator.coefficients.values.all { it == zero }) throw ArithmeticException("/ by zero")
|
||||
else LabeledRationalFunction<C>(numerator, denominator)
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> LabeledRationalFunctionSpace<C, A>.LabeledRationalFunction(numeratorCoefficients: Map<Map<Symbol, UInt>, C>, denominatorCoefficients: Map<Map<Symbol, UInt>, C>): LabeledRationalFunction<C> =
|
||||
if (denominatorCoefficients.values.all { it == zero }) throw ArithmeticException("/ by zero")
|
||||
else LabeledRationalFunction<C>(
|
||||
LabeledPolynomial(numeratorCoefficients),
|
||||
LabeledPolynomial(denominatorCoefficients)
|
||||
LabeledRationalFunction<C>(
|
||||
LabeledPolynomial(numeratorCoefficients, toCheckInput = true),
|
||||
LabeledPolynomial(denominatorCoefficients, toCheckInput = true)
|
||||
)
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> A.LabeledRationalFunction(numeratorCoefficients: Map<Map<Symbol, UInt>, C>, denominatorCoefficients: Map<Map<Symbol, UInt>, C>): LabeledRationalFunction<C> =
|
||||
if (denominatorCoefficients.values.all { it == zero }) throw ArithmeticException("/ by zero")
|
||||
else LabeledRationalFunction<C>(
|
||||
LabeledPolynomial(numeratorCoefficients),
|
||||
LabeledPolynomial(denominatorCoefficients)
|
||||
LabeledRationalFunction<C>(
|
||||
LabeledPolynomial(numeratorCoefficients, toCheckInput = true),
|
||||
LabeledPolynomial(denominatorCoefficients, toCheckInput = true)
|
||||
)
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> LabeledRationalFunctionSpace<C, A>.LabeledRationalFunction(numerator: LabeledPolynomial<C>): LabeledRationalFunction<C> =
|
||||
LabeledRationalFunction<C>(numerator, polynomialOne)
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> A.LabeledRationalFunction(numerator: LabeledPolynomial<C>): LabeledRationalFunction<C> =
|
||||
LabeledRationalFunction<C>(numerator, LabeledPolynomial(mapOf(emptyMap<Symbol, UInt>() to one)))
|
||||
LabeledRationalFunction<C>(numerator, LabeledPolynomial(mapOf(emptyMap<Symbol, UInt>() to one), toCheckInput = false))
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> LabeledRationalFunctionSpace<C, A>.LabeledRationalFunction(numeratorCoefficients: Map<Map<Symbol, UInt>, C>): LabeledRationalFunction<C> =
|
||||
LabeledRationalFunction<C>(
|
||||
LabeledPolynomial(numeratorCoefficients),
|
||||
LabeledPolynomial(numeratorCoefficients, toCheckInput = true),
|
||||
polynomialOne
|
||||
)
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> A.LabeledRationalFunction(numeratorCoefficients: Map<Map<Symbol, UInt>, C>): LabeledRationalFunction<C> =
|
||||
LabeledRationalFunction<C>(
|
||||
LabeledPolynomial(numeratorCoefficients),
|
||||
LabeledPolynomial(mapOf(emptyMap<Symbol, UInt>() to one))
|
||||
LabeledPolynomial(numeratorCoefficients, toCheckInput = true),
|
||||
LabeledPolynomial(mapOf(emptyMap<Symbol, UInt>() to one), toCheckInput = false)
|
||||
)
|
||||
|
||||
public class LabeledRationalFunctionSpace<C, A: Ring<C>>(
|
||||
@ -82,38 +72,16 @@ public class LabeledRationalFunctionSpace<C, A: Ring<C>>(
|
||||
numerator: LabeledPolynomial<C>,
|
||||
denominator: LabeledPolynomial<C>
|
||||
): LabeledRationalFunction<C> =
|
||||
LabeledRationalFunction(numerator, denominator)
|
||||
LabeledRationalFunction<C>(numerator, denominator)
|
||||
|
||||
/**
|
||||
* Instance of zero rational function (zero of the rational functions ring).
|
||||
*/
|
||||
public override val zero: LabeledRationalFunction<C> = LabeledRationalFunction(polynomialZero, polynomialOne)
|
||||
public override val zero: LabeledRationalFunction<C> = LabeledRationalFunction<C>(polynomialZero, polynomialOne)
|
||||
/**
|
||||
* Instance of unit polynomial (unit of the rational functions ring).
|
||||
*/
|
||||
public override val one: LabeledRationalFunction<C> = LabeledRationalFunction(polynomialOne, polynomialOne)
|
||||
|
||||
/**
|
||||
* Checks equality of the rational functions.
|
||||
*/
|
||||
public override infix fun LabeledRationalFunction<C>.equalsTo(other: LabeledRationalFunction<C>): 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<C> = LabeledRationalFunction<C>(polynomialOne, polynomialOne)
|
||||
|
||||
// TODO: Разобрать
|
||||
|
||||
|
@ -91,13 +91,9 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
|
||||
.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<C, A : Ring<C>>(
|
||||
.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<C, A : Ring<C>>(
|
||||
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<C, A : Ring<C>>(
|
||||
.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<C, A : Ring<C>>(
|
||||
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<C, A : Ring<C>>(
|
||||
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<C, A : Ring<C>>(
|
||||
* Returns sum of the constant represented as polynomial and the polynomial.
|
||||
*/
|
||||
public override operator fun C.plus(other: ListPolynomial<C>): ListPolynomial<C> =
|
||||
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<C, A : Ring<C>>(
|
||||
* Returns difference between the constant represented as polynomial and the polynomial.
|
||||
*/
|
||||
public override operator fun C.minus(other: ListPolynomial<C>): ListPolynomial<C> =
|
||||
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<C, A : Ring<C>>(
|
||||
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<C, A : Ring<C>>(
|
||||
* Returns product of the constant represented as polynomial and the polynomial.
|
||||
*/
|
||||
public override operator fun C.times(other: ListPolynomial<C>): ListPolynomial<C> =
|
||||
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<C, A : Ring<C>>(
|
||||
* Returns sum of the constant represented as polynomial and the polynomial.
|
||||
*/
|
||||
public override operator fun ListPolynomial<C>.plus(other: C): ListPolynomial<C> =
|
||||
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<C, A : Ring<C>>(
|
||||
* Returns difference between the constant represented as polynomial and the polynomial.
|
||||
*/
|
||||
public override operator fun ListPolynomial<C>.minus(other: C): ListPolynomial<C> =
|
||||
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<C, A : Ring<C>>(
|
||||
* Returns product of the constant represented as polynomial and the polynomial.
|
||||
*/
|
||||
public override operator fun ListPolynomial<C>.times(other: C): ListPolynomial<C> =
|
||||
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<C, A : Ring<C>>(
|
||||
/**
|
||||
* Converts the constant [value] to polynomial.
|
||||
*/
|
||||
public override fun number(value: C): ListPolynomial<C> =
|
||||
if (value.isZero()) zero
|
||||
else ListPolynomial(value)
|
||||
public override fun number(value: C): ListPolynomial<C> = ListPolynomial(value)
|
||||
|
||||
/**
|
||||
* Returns negation of the polynomial.
|
||||
@ -330,7 +294,7 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
|
||||
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<C, A : Ring<C>>(
|
||||
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,38 +325,14 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
|
||||
public override operator fun ListPolynomial<C>.times(other: ListPolynomial<C>): ListPolynomial<C> {
|
||||
val thisDegree = degree
|
||||
val otherDegree = other.degree
|
||||
return when {
|
||||
thisDegree == -1 -> zero
|
||||
otherDegree == -1 -> zero
|
||||
else ->
|
||||
ListPolynomial(
|
||||
Coefficients(thisDegree + otherDegree + 1) { d ->
|
||||
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<C>.isZero(): Boolean = coefficients.all { it.isZero() }
|
||||
/**
|
||||
* Check if the instant is unit polynomial.
|
||||
*/
|
||||
public override fun ListPolynomial<C>.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<C>.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<C, A : Ring<C>>(
|
||||
*/
|
||||
override val one: ListPolynomial<C> = ListPolynomial(listOf(constantOne))
|
||||
|
||||
/**
|
||||
* Checks equality of the polynomials.
|
||||
*/
|
||||
public override infix fun ListPolynomial<C>.equalsTo(other: ListPolynomial<C>): 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<C>.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<C>.asConstantOrNull(): C? =
|
||||
with(coefficients) {
|
||||
when {
|
||||
isEmpty() -> constantZero
|
||||
withIndex().all { (index, c) -> index == 0 || c.isZero() } -> first()
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
public override val ListPolynomial<C>.degree: Int get() = coefficients.lastIndex
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
public inline fun ListPolynomial<C>.substitute(argument: C): C = this.substitute(ring, argument)
|
||||
@ -451,44 +368,6 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
|
||||
public inline operator fun ListPolynomial<C>.invoke(argument: C): C = this.substitute(ring, argument)
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
public inline operator fun ListPolynomial<C>.invoke(argument: ListPolynomial<C>): ListPolynomial<C> = this.substitute(ring, argument)
|
||||
|
||||
// TODO: Move to other internal utilities with context receiver
|
||||
@JvmName("applyAndRemoveZerosInternal")
|
||||
internal inline fun MutableList<C>.applyAndRemoveZeros(block: MutableList<C>.() -> Unit) : MutableList<C> {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
block()
|
||||
while (isNotEmpty() && elementAt(lastIndex).isZero()) removeAt(lastIndex)
|
||||
return this
|
||||
}
|
||||
internal inline fun List<C>.applyAndRemoveZeros(block: MutableList<C>.() -> Unit) : List<C> =
|
||||
toMutableList().applyAndRemoveZeros(block)
|
||||
@Suppress("FunctionName")
|
||||
internal inline fun MutableCoefficients(size: Int, init: (index: Int) -> C): MutableList<C> {
|
||||
val list = ArrayList<C>(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<C> = MutableCoefficients(size, init)
|
||||
@OptIn(ExperimentalTypeInference::class)
|
||||
internal inline fun buildCoefficients(@BuilderInference builderAction: MutableList<C>.() -> Unit): List<C> {
|
||||
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<C>.() -> Unit): List<C> {
|
||||
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
|
||||
return buildList(capacity) {
|
||||
builderAction()
|
||||
while (isNotEmpty() && elementAt(lastIndex).isZero()) removeAt(lastIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -8,7 +8,7 @@ package space.kscience.kmath.functions
|
||||
import space.kscience.kmath.operations.Ring
|
||||
|
||||
|
||||
public data class ListRationalFunction<C> internal constructor (
|
||||
public data class ListRationalFunction<C>(
|
||||
public override val numerator: ListPolynomial<C>,
|
||||
public override val denominator: ListPolynomial<C>
|
||||
) : RationalFunction<C, ListPolynomial<C>> {
|
||||
@ -17,25 +17,15 @@ public data class ListRationalFunction<C> internal constructor (
|
||||
|
||||
// Waiting for context receivers :( TODO: Replace with context receivers when they will be available
|
||||
|
||||
@Suppress("FunctionName")
|
||||
internal fun <C, A: Ring<C>> ListRationalFunctionSpace<C, A>.ListRationalFunction(numerator: ListPolynomial<C>, denominator: ListPolynomial<C>): ListRationalFunction<C> =
|
||||
if (denominator.isZero()) throw ArithmeticException("/ by zero")
|
||||
else ListRationalFunction<C>(numerator, denominator)
|
||||
@Suppress("FunctionName")
|
||||
internal fun <C, A: Ring<C>> A.ListRationalFunction(numerator: ListPolynomial<C>, denominator: ListPolynomial<C>): ListRationalFunction<C> =
|
||||
if (denominator.coefficients.all { it == zero }) throw ArithmeticException("/ by zero")
|
||||
else ListRationalFunction<C>(numerator, denominator)
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> ListRationalFunctionSpace<C, A>.ListRationalFunction(numeratorCoefficients: List<C>, denominatorCoefficients: List<C>, reverse: Boolean = false): ListRationalFunction<C> =
|
||||
if (denominatorCoefficients.all { it == zero }) throw ArithmeticException("/ by zero")
|
||||
else ListRationalFunction<C>(
|
||||
ListRationalFunction<C>(
|
||||
ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ),
|
||||
ListPolynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } )
|
||||
)
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> A.ListRationalFunction(numeratorCoefficients: List<C>, denominatorCoefficients: List<C>, reverse: Boolean = false): ListRationalFunction<C> =
|
||||
if (denominatorCoefficients.all { it == zero }) throw ArithmeticException("/ by zero")
|
||||
else ListRationalFunction<C>(
|
||||
ListRationalFunction<C>(
|
||||
ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ),
|
||||
ListPolynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } )
|
||||
)
|
||||
|
@ -58,6 +58,8 @@ internal fun List<UInt>.cleanUp() = subList(0, indexOfLast { it != 0U } + 1)
|
||||
|
||||
@Suppress("FunctionName", "NOTHING_TO_INLINE")
|
||||
internal inline fun <C, A: Ring<C>> NumberedPolynomialSpace<C, A>.NumberedPolynomial(coefs: Map<List<UInt>, C>, toCheckInput: Boolean = true) : NumberedPolynomial<C> = ring.NumberedPolynomial(coefs, toCheckInput)
|
||||
@Suppress("FunctionName", "NOTHING_TO_INLINE")
|
||||
internal inline fun <C, A: Ring<C>> NumberedRationalFunctionSpace<C, A>.NumberedPolynomial(coefs: Map<List<UInt>, C>, toCheckInput: Boolean = true) : NumberedPolynomial<C> = ring.NumberedPolynomial(coefs, toCheckInput)
|
||||
@Suppress("FunctionName")
|
||||
internal fun <C, A: Ring<C>> A.NumberedPolynomial(coefs: Map<List<UInt>, C>, toCheckInput: Boolean = true) : NumberedPolynomial<C> {
|
||||
if (!toCheckInput) return NumberedPolynomial<C>(coefs)
|
||||
@ -70,13 +72,13 @@ internal fun <C, A: Ring<C>> A.NumberedPolynomial(coefs: Map<List<UInt>, C>, toC
|
||||
fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value
|
||||
}
|
||||
|
||||
return NumberedPolynomial<C>(
|
||||
fixedCoefs.filterValues { it != zero }
|
||||
)
|
||||
return NumberedPolynomial<C>(fixedCoefs)
|
||||
}
|
||||
|
||||
@Suppress("FunctionName", "NOTHING_TO_INLINE")
|
||||
internal inline fun <C, A: Ring<C>> NumberedPolynomialSpace<C, A>.NumberedPolynomial(pairs: Collection<Pair<List<UInt>, C>>, toCheckInput: Boolean = true) : NumberedPolynomial<C> = ring.NumberedPolynomial(pairs, toCheckInput)
|
||||
@Suppress("FunctionName", "NOTHING_TO_INLINE")
|
||||
internal inline fun <C, A: Ring<C>> NumberedRationalFunctionSpace<C, A>.NumberedPolynomial(pairs: Collection<Pair<List<UInt>, C>>, toCheckInput: Boolean = true) : NumberedPolynomial<C> = ring.NumberedPolynomial(pairs, toCheckInput)
|
||||
@Suppress("FunctionName")
|
||||
internal fun <C, A: Ring<C>> A.NumberedPolynomial(pairs: Collection<Pair<List<UInt>, C>>, toCheckInput: Boolean = true) : NumberedPolynomial<C> {
|
||||
if (!toCheckInput) return NumberedPolynomial<C>(pairs.toMap())
|
||||
@ -89,13 +91,13 @@ internal fun <C, A: Ring<C>> A.NumberedPolynomial(pairs: Collection<Pair<List<UI
|
||||
fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value
|
||||
}
|
||||
|
||||
return NumberedPolynomial<C>(
|
||||
fixedCoefs.filterValues { it != zero }
|
||||
)
|
||||
return NumberedPolynomial<C>(fixedCoefs)
|
||||
}
|
||||
|
||||
@Suppress("FunctionName", "NOTHING_TO_INLINE")
|
||||
internal inline fun <C, A: Ring<C>> NumberedPolynomialSpace<C, A>.NumberedPolynomial(vararg pairs: Pair<List<UInt>, C>, toCheckInput: Boolean = true) : NumberedPolynomial<C> = ring.NumberedPolynomial(pairs = pairs, toCheckInput = toCheckInput)
|
||||
@Suppress("FunctionName", "NOTHING_TO_INLINE")
|
||||
internal inline fun <C, A: Ring<C>> NumberedRationalFunctionSpace<C, A>.NumberedPolynomial(vararg pairs: Pair<List<UInt>, C>, toCheckInput: Boolean = true) : NumberedPolynomial<C> = ring.NumberedPolynomial(pairs = pairs, toCheckInput = toCheckInput)
|
||||
@Suppress("FunctionName")
|
||||
internal fun <C, A: Ring<C>> A.NumberedPolynomial(vararg pairs: Pair<List<UInt>, C>, toCheckInput: Boolean = true) : NumberedPolynomial<C> {
|
||||
if (!toCheckInput) return NumberedPolynomial<C>(pairs.toMap())
|
||||
@ -108,25 +110,29 @@ internal fun <C, A: Ring<C>> A.NumberedPolynomial(vararg pairs: Pair<List<UInt>,
|
||||
fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value
|
||||
}
|
||||
|
||||
return NumberedPolynomial<C>(
|
||||
fixedCoefs.filterValues { it != zero }
|
||||
)
|
||||
return NumberedPolynomial<C>(fixedCoefs)
|
||||
}
|
||||
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> A.NumberedPolynomial(coefs: Map<List<UInt>, C>) : NumberedPolynomial<C> = NumberedPolynomial(coefs, toCheckInput = true)
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> NumberedPolynomialSpace<C, A>.NumberedPolynomial(coefs: Map<List<UInt>, C>) : NumberedPolynomial<C> = NumberedPolynomial(coefs, toCheckInput = true)
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> NumberedRationalFunctionSpace<C, A>.NumberedPolynomial(coefs: Map<List<UInt>, C>) : NumberedPolynomial<C> = NumberedPolynomial(coefs, toCheckInput = true)
|
||||
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> A.NumberedPolynomial(pairs: Collection<Pair<List<UInt>, C>>) : NumberedPolynomial<C> = NumberedPolynomial(pairs, toCheckInput = true)
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> NumberedPolynomialSpace<C, A>.NumberedPolynomial(pairs: Collection<Pair<List<UInt>, C>>) : NumberedPolynomial<C> = NumberedPolynomial(pairs, toCheckInput = true)
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> NumberedRationalFunctionSpace<C, A>.NumberedPolynomial(pairs: Collection<Pair<List<UInt>, C>>) : NumberedPolynomial<C> = NumberedPolynomial(pairs, toCheckInput = true)
|
||||
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> A.NumberedPolynomial(vararg pairs: Pair<List<UInt>, C>) : NumberedPolynomial<C> = NumberedPolynomial(*pairs, toCheckInput = true)
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> NumberedPolynomialSpace<C, A>.NumberedPolynomial(vararg pairs: Pair<List<UInt>, C>) : NumberedPolynomial<C> = NumberedPolynomial(*pairs, toCheckInput = true)
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> NumberedRationalFunctionSpace<C, A>.NumberedPolynomial(vararg pairs: Pair<List<UInt>, C>) : NumberedPolynomial<C> = NumberedPolynomial(*pairs, toCheckInput = true)
|
||||
|
||||
//context(A)
|
||||
//public fun <C, A: Ring<C>> Symbol.asNumberedPolynomial() : NumberedPolynomial<C> = NumberedPolynomial<C>(mapOf(mapOf(this to 1u) to one))
|
||||
@ -211,10 +217,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
||||
.apply {
|
||||
val degs = emptyList<UInt>()
|
||||
|
||||
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<C, A : Ring<C>>(
|
||||
.apply {
|
||||
val degs = emptyList<UInt>()
|
||||
|
||||
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<C, A : Ring<C>>(
|
||||
if (other == 0) zero
|
||||
else NumberedPolynomial<C>(
|
||||
coefficients
|
||||
.applyAndRemoveZeros {
|
||||
.toMutableMap()
|
||||
.apply {
|
||||
for (degs in keys) this[degs] = this[degs]!! * other
|
||||
}
|
||||
)
|
||||
@ -265,10 +266,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
||||
.apply {
|
||||
val degs = emptyList<UInt>()
|
||||
|
||||
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<C, A : Ring<C>>(
|
||||
.apply {
|
||||
val degs = emptyList<UInt>()
|
||||
|
||||
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<C, A : Ring<C>>(
|
||||
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<C, A : Ring<C>>(
|
||||
* Returns sum of the constant represented as polynomial and the polynomial.
|
||||
*/
|
||||
override operator fun C.plus(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
||||
if (this.isZero()) other
|
||||
else with(other.coefficients) {
|
||||
with(other.coefficients) {
|
||||
if (isEmpty()) NumberedPolynomial<C>(mapOf(emptyList<UInt>() to this@plus))
|
||||
else NumberedPolynomial<C>(
|
||||
toMutableMap()
|
||||
.apply {
|
||||
val degs = emptyList<UInt>()
|
||||
|
||||
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<C, A : Ring<C>>(
|
||||
* Returns difference between the constant represented as polynomial and the polynomial.
|
||||
*/
|
||||
override operator fun C.minus(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
||||
if (this.isZero()) -other
|
||||
else with(other.coefficients) {
|
||||
with(other.coefficients) {
|
||||
if (isEmpty()) NumberedPolynomial<C>(mapOf(emptyList<UInt>() to this@minus))
|
||||
else NumberedPolynomial<C>(
|
||||
toMutableMap()
|
||||
@ -343,10 +334,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
||||
|
||||
val degs = emptyList<UInt>()
|
||||
|
||||
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<C, A : Ring<C>>(
|
||||
* Returns product of the constant represented as polynomial and the polynomial.
|
||||
*/
|
||||
override operator fun C.times(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
||||
if (this.isZero()) zero
|
||||
else NumberedPolynomial<C>(
|
||||
NumberedPolynomial<C>(
|
||||
other.coefficients
|
||||
.applyAndRemoveZeros {
|
||||
.toMutableMap()
|
||||
.apply {
|
||||
for (degs in keys) this[degs] = this@times * this[degs]!!
|
||||
}
|
||||
)
|
||||
@ -366,18 +354,14 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
||||
* Returns sum of the constant represented as polynomial and the polynomial.
|
||||
*/
|
||||
override operator fun NumberedPolynomial<C>.plus(other: C): NumberedPolynomial<C> =
|
||||
if (other.isZero()) this
|
||||
else with(coefficients) {
|
||||
with(coefficients) {
|
||||
if (isEmpty()) NumberedPolynomial<C>(mapOf(emptyList<UInt>() to other))
|
||||
else NumberedPolynomial<C>(
|
||||
toMutableMap()
|
||||
.apply {
|
||||
val degs = emptyList<UInt>()
|
||||
|
||||
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<C, A : Ring<C>>(
|
||||
* Returns difference between the constant represented as polynomial and the polynomial.
|
||||
*/
|
||||
override operator fun NumberedPolynomial<C>.minus(other: C): NumberedPolynomial<C> =
|
||||
if (other.isZero()) this
|
||||
else with(coefficients) {
|
||||
with(coefficients) {
|
||||
if (isEmpty()) NumberedPolynomial<C>(mapOf(emptyList<UInt>() to other))
|
||||
else NumberedPolynomial<C>(
|
||||
toMutableMap()
|
||||
.apply {
|
||||
val degs = emptyList<UInt>()
|
||||
|
||||
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<C, A : Ring<C>>(
|
||||
* Returns product of the constant represented as polynomial and the polynomial.
|
||||
*/
|
||||
override operator fun NumberedPolynomial<C>.times(other: C): NumberedPolynomial<C> =
|
||||
if (other.isZero()) zero
|
||||
else NumberedPolynomial<C>(
|
||||
NumberedPolynomial<C>(
|
||||
coefficients
|
||||
.applyAndRemoveZeros {
|
||||
.toMutableMap()
|
||||
.apply {
|
||||
for (degs in keys) this[degs] = this[degs]!! * other
|
||||
}
|
||||
)
|
||||
@ -416,8 +396,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
||||
* Converts the constant [value] to polynomial.
|
||||
*/
|
||||
public override fun number(value: C): NumberedPolynomial<C> =
|
||||
if (value == 0) zero
|
||||
else NumberedPolynomial(mapOf(emptyList<UInt>() to value))
|
||||
NumberedPolynomial(mapOf(emptyList<UInt>() to value))
|
||||
|
||||
/**
|
||||
* Returns negation of the polynomial.
|
||||
@ -431,7 +410,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
||||
*/
|
||||
override operator fun NumberedPolynomial<C>.plus(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
||||
NumberedPolynomial<C>(
|
||||
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<C, A : Ring<C>>(
|
||||
*/
|
||||
override operator fun NumberedPolynomial<C>.minus(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
||||
NumberedPolynomial<C>(
|
||||
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,12 +429,8 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
||||
* Returns product of the polynomials.
|
||||
*/
|
||||
override operator fun NumberedPolynomial<C>.times(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
||||
when {
|
||||
isZero() -> zero
|
||||
other.isZero() -> zero
|
||||
else ->
|
||||
NumberedPolynomial<C>(
|
||||
buildCoefficients(coefficients.size * other.coefficients.size) {
|
||||
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))
|
||||
@ -465,42 +440,6 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the instant is zero polynomial.
|
||||
*/
|
||||
public override fun NumberedPolynomial<C>.isZero(): Boolean = coefficients.values.all { it.isZero() }
|
||||
/**
|
||||
* Check if the instant is unit polynomial.
|
||||
*/
|
||||
public override fun NumberedPolynomial<C>.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
|
||||
}
|
||||
/**
|
||||
* Check if the instant is minus unit polynomial.
|
||||
*/
|
||||
public override fun NumberedPolynomial<C>.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<C, A : Ring<C>>(
|
||||
)
|
||||
)
|
||||
|
||||
/**
|
||||
* Checks equality of the polynomials.
|
||||
*/
|
||||
override infix fun NumberedPolynomial<C>.equalsTo(other: NumberedPolynomial<C>): 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<C>.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<C>.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<C, A : Ring<C>>(
|
||||
public val NumberedPolynomial<C>.degrees: List<UInt>
|
||||
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<C, A : Ring<C>>(
|
||||
* Counts degree of the polynomial by the specified [variable].
|
||||
*/
|
||||
public fun NumberedPolynomial<C>.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<C>.degreeBy(variables: Collection<Int>): 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<C, A : Ring<C>>(
|
||||
public val NumberedPolynomial<C>.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<C>.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<C>.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<C>.asConstantOrNull(): C? =
|
||||
with(coefficients) {
|
||||
if(isConstant()) getOrElse(emptyList()) { constantZero }
|
||||
else null
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
public inline fun NumberedPolynomial<C>.substitute(argument: Map<Int, C>): NumberedPolynomial<C> = this.substitute(ring, argument)
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
@ -629,35 +528,6 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
||||
@JvmName("invokePolynomial")
|
||||
public inline operator fun NumberedPolynomial<C>.invoke(argument: Map<Int, NumberedPolynomial<C>>): NumberedPolynomial<C> = this.substitute(ring, argument)
|
||||
|
||||
// TODO: Move to other internal utilities with context receiver
|
||||
@JvmName("applyAndRemoveZerosInternal")
|
||||
internal fun MutableMap<List<UInt>, C>.applyAndRemoveZeros(block: MutableMap<List<UInt>, C>.() -> Unit) : MutableMap<List<UInt>, C> {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
block()
|
||||
for ((degs, c) in this) if (c.isZero()) this.remove(degs)
|
||||
return this
|
||||
}
|
||||
internal fun Map<List<UInt>, C>.applyAndRemoveZeros(block: MutableMap<List<UInt>, C>.() -> Unit) : Map<List<UInt>, C> =
|
||||
toMutableMap().applyAndRemoveZeros(block)
|
||||
@OptIn(ExperimentalTypeInference::class)
|
||||
internal inline fun buildCoefficients(@BuilderInference builderAction: MutableMap<List<UInt>, C>.() -> Unit): Map<List<UInt>, 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<List<UInt>, C>.() -> Unit): Map<List<UInt>, 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<C> = NumberedPolynomial<C>(mapOf(emptyList<UInt>() to this))
|
||||
}
|
@ -19,45 +19,35 @@ public class NumberedRationalFunction<C> internal constructor(
|
||||
|
||||
// Waiting for context receivers :( TODO: Replace with context receivers when they will be available
|
||||
|
||||
@Suppress("FunctionName")
|
||||
internal fun <C, A: Ring<C>> NumberedRationalFunctionSpace<C, A>.NumberedRationalFunction(numerator: NumberedPolynomial<C>, denominator: NumberedPolynomial<C>): NumberedRationalFunction<C> =
|
||||
if (denominator.isZero()) throw ArithmeticException("/ by zero")
|
||||
else NumberedRationalFunction<C>(numerator, denominator)
|
||||
@Suppress("FunctionName")
|
||||
internal fun <C, A: Ring<C>> A.NumberedRationalFunction(numerator: NumberedPolynomial<C>, denominator: NumberedPolynomial<C>): NumberedRationalFunction<C> =
|
||||
if (denominator.coefficients.values.all { it == zero }) throw ArithmeticException("/ by zero")
|
||||
else NumberedRationalFunction<C>(numerator, denominator)
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> NumberedRationalFunctionSpace<C, A>.NumberedRationalFunction(numeratorCoefficients: Map<List<UInt>, C>, denominatorCoefficients: Map<List<UInt>, C>): NumberedRationalFunction<C> =
|
||||
if (denominatorCoefficients.values.all { it == zero }) throw ArithmeticException("/ by zero")
|
||||
else NumberedRationalFunction<C>(
|
||||
NumberedPolynomial(numeratorCoefficients),
|
||||
NumberedPolynomial(denominatorCoefficients)
|
||||
NumberedRationalFunction<C>(
|
||||
NumberedPolynomial(numeratorCoefficients, toCheckInput = true),
|
||||
NumberedPolynomial(denominatorCoefficients, toCheckInput = true)
|
||||
)
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> A.NumberedRationalFunction(numeratorCoefficients: Map<List<UInt>, C>, denominatorCoefficients: Map<List<UInt>, C>): NumberedRationalFunction<C> =
|
||||
if (denominatorCoefficients.values.all { it == zero }) throw ArithmeticException("/ by zero")
|
||||
else NumberedRationalFunction<C>(
|
||||
NumberedPolynomial(numeratorCoefficients),
|
||||
NumberedPolynomial(denominatorCoefficients)
|
||||
NumberedRationalFunction<C>(
|
||||
NumberedPolynomial(numeratorCoefficients, toCheckInput = true),
|
||||
NumberedPolynomial(denominatorCoefficients, toCheckInput = true)
|
||||
)
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> NumberedRationalFunctionSpace<C, A>.NumberedRationalFunction(numerator: NumberedPolynomial<C>): NumberedRationalFunction<C> =
|
||||
NumberedRationalFunction<C>(numerator, polynomialOne)
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> A.NumberedRationalFunction(numerator: NumberedPolynomial<C>): NumberedRationalFunction<C> =
|
||||
NumberedRationalFunction<C>(numerator, NumberedPolynomial(mapOf(emptyList<UInt>() to one)))
|
||||
NumberedRationalFunction<C>(numerator, NumberedPolynomial(mapOf(emptyList<UInt>() to one), toCheckInput = false))
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> NumberedRationalFunctionSpace<C, A>.NumberedRationalFunction(numeratorCoefficients: Map<List<UInt>, C>): NumberedRationalFunction<C> =
|
||||
NumberedRationalFunction<C>(
|
||||
NumberedPolynomial(numeratorCoefficients),
|
||||
NumberedPolynomial(numeratorCoefficients, toCheckInput = true),
|
||||
polynomialOne
|
||||
)
|
||||
@Suppress("FunctionName")
|
||||
public fun <C, A: Ring<C>> A.NumberedRationalFunction(numeratorCoefficients: Map<List<UInt>, C>): NumberedRationalFunction<C> =
|
||||
NumberedRationalFunction<C>(
|
||||
NumberedPolynomial(numeratorCoefficients),
|
||||
NumberedPolynomial(mapOf(emptyList<UInt>() to one))
|
||||
NumberedPolynomial(numeratorCoefficients, toCheckInput = true),
|
||||
NumberedPolynomial(mapOf(emptyList<UInt>() to one), toCheckInput = false)
|
||||
)
|
||||
|
||||
public class NumberedRationalFunctionSpace<C, A: Ring<C>> (
|
||||
@ -91,28 +81,6 @@ public class NumberedRationalFunctionSpace<C, A: Ring<C>> (
|
||||
*/
|
||||
public override val one: NumberedRationalFunction<C> = NumberedRationalFunction(polynomialOne, polynomialOne)
|
||||
|
||||
/**
|
||||
* Checks equality of the rational functions.
|
||||
*/
|
||||
public override infix fun NumberedRationalFunction<C>.equalsTo(other: NumberedRationalFunction<C>): 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<C, A: Ring<C>> (
|
||||
public val NumberedRationalFunction<C>.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
|
||||
}
|
||||
}
|
||||
|
@ -155,31 +155,6 @@ public interface PolynomialSpace<C, P: Polynomial<C>> : Ring<P> {
|
||||
@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<C, P: Polynomial<C>> : Ring<P> {
|
||||
*/
|
||||
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<C, P: Polynomial<C>> : Ring<P> {
|
||||
*/
|
||||
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
|
||||
}
|
||||
|
@ -222,31 +222,6 @@ public interface RationalFunctionalSpace<C, P: Polynomial<C>, 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<C, P: Polynomial<C>, 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<C, P: Polynomial<C>, 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<C, P: Polynomial<C>, 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<C, P: Polynomial<C>, 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).
|
||||
|
@ -121,9 +121,9 @@ public fun <C> ListPolynomial<C>.substitute(ring: Ring<C>, arg: C): C = ring {
|
||||
public fun <C> ListPolynomial<C>.substitute(ring: Ring<C>, arg: ListPolynomial<C>) : ListPolynomial<C> = 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<C> = MutableList(thisDegree * argDegree + 1) { constantZero }
|
||||
@ -144,7 +144,6 @@ public fun <C> ListPolynomial<C>.substitute(ring: Ring<C>, arg: ListPolynomial<C
|
||||
resultDegree += argDegree
|
||||
}
|
||||
|
||||
with(resultCoefs) { while (isNotEmpty() && elementAt(lastIndex) == constantZero) removeAt(lastIndex) }
|
||||
return ListPolynomial<C>(resultCoefs)
|
||||
}
|
||||
|
||||
@ -168,7 +167,6 @@ public fun <C, A> ListPolynomial<C>.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 <C, A> ListPolynomial<C>.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 <C, A> ListPolynomial<C>.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 <C, A> ListPolynomial<C>.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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -55,11 +55,11 @@ public fun <C> ListRationalFunction<C>.substitute(ring: Field<C>, arg: C): C = r
|
||||
internal fun <C> ListPolynomial<C>.substituteRationalFunctionTakeNumerator(ring: Ring<C>, arg: ListRationalFunction<C>): ListPolynomial<C> = 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<Int>(thisDegreeLog2 + 1) {
|
||||
|
@ -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<Rational>().isZero() }
|
||||
assertTrue("test 2") { ListPolynomial<Rational>(Rational(0)).isZero() }
|
||||
assertTrue("test 3") { ListPolynomial<Rational>(Rational(0), Rational(0)).isZero() }
|
||||
assertTrue("test 4") { ListPolynomial<Rational>(Rational(0), Rational(0), Rational(0))
|
||||
.isZero() }
|
||||
assertFalse("test 5") { ListPolynomial<Rational>(Rational(3, 5)).isZero() }
|
||||
assertFalse("test 6") { ListPolynomial<Rational>(Rational(3, 5), Rational(0))
|
||||
.isZero() }
|
||||
assertFalse("test 7") { ListPolynomial<Rational>(Rational(0), Rational(3, 5), Rational(0))
|
||||
.isZero() }
|
||||
}
|
||||
}
|
||||
@Test
|
||||
fun test_Polynomial_isOne() {
|
||||
RationalField.listPolynomial {
|
||||
assertFalse("test 1") { ListPolynomial<Rational>().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<Rational>().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<Rational>().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"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -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(
|
||||
|
Loading…
Reference in New Issue
Block a user