Feature: Polynomials and rational functions #469
@ -58,6 +58,8 @@ internal fun Map<Symbol, UInt>.cleanUp() = filterValues { it > 0U }
|
|||||||
|
|
||||||
@Suppress("FunctionName", "NOTHING_TO_INLINE")
|
@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)
|
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")
|
@Suppress("FunctionName")
|
||||||
internal fun <C, A: Ring<C>> A.LabeledPolynomial(coefs: Map<Map<Symbol, UInt>, C>, toCheckInput: Boolean = true) : LabeledPolynomial<C> {
|
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)
|
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
|
fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value
|
||||||
}
|
}
|
||||||
|
|
||||||
return LabeledPolynomial<C>(
|
return LabeledPolynomial<C>(fixedCoefs)
|
||||||
fixedCoefs.filterValues { it != zero }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("FunctionName", "NOTHING_TO_INLINE")
|
@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)
|
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")
|
@Suppress("FunctionName")
|
||||||
internal fun <C, A: Ring<C>> A.LabeledPolynomial(pairs: Collection<Pair<Map<Symbol, UInt>, C>>, toCheckInput: Boolean = true) : LabeledPolynomial<C> {
|
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())
|
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
|
fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value
|
||||||
}
|
}
|
||||||
|
|
||||||
return LabeledPolynomial<C>(
|
return LabeledPolynomial<C>(fixedCoefs)
|
||||||
fixedCoefs.filterValues { it != zero }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("FunctionName", "NOTHING_TO_INLINE")
|
@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)
|
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")
|
@Suppress("FunctionName")
|
||||||
internal fun <C, A: Ring<C>> A.LabeledPolynomial(vararg pairs: Pair<Map<Symbol, UInt>, C>, toCheckInput: Boolean = true) : LabeledPolynomial<C> {
|
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())
|
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
|
fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value
|
||||||
}
|
}
|
||||||
|
|
||||||
return LabeledPolynomial<C>(
|
return LabeledPolynomial<C>(fixedCoefs)
|
||||||
fixedCoefs.filterValues { it != zero }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
public fun <C, A: Ring<C>> A.LabeledPolynomial(coefs: Map<Map<Symbol, UInt>, C>) : LabeledPolynomial<C> = LabeledPolynomial(coefs, toCheckInput = true)
|
public fun <C, A: Ring<C>> A.LabeledPolynomial(coefs: Map<Map<Symbol, UInt>, C>) : LabeledPolynomial<C> = LabeledPolynomial(coefs, toCheckInput = true)
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
public fun <C, A: Ring<C>> LabeledPolynomialSpace<C, A>.LabeledPolynomial(coefs: Map<Map<Symbol, UInt>, C>) : LabeledPolynomial<C> = LabeledPolynomial(coefs, toCheckInput = true)
|
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")
|
@Suppress("FunctionName")
|
||||||
public fun <C, A: Ring<C>> A.LabeledPolynomial(pairs: Collection<Pair<Map<Symbol, UInt>, C>>) : LabeledPolynomial<C> = LabeledPolynomial(pairs, toCheckInput = true)
|
public fun <C, A: Ring<C>> A.LabeledPolynomial(pairs: Collection<Pair<Map<Symbol, UInt>, C>>) : LabeledPolynomial<C> = LabeledPolynomial(pairs, toCheckInput = true)
|
||||||
@Suppress("FunctionName")
|
@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)
|
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")
|
@Suppress("FunctionName")
|
||||||
public fun <C, A: Ring<C>> A.LabeledPolynomial(vararg pairs: Pair<Map<Symbol, UInt>, C>) : LabeledPolynomial<C> = LabeledPolynomial(*pairs, toCheckInput = true)
|
public fun <C, A: Ring<C>> A.LabeledPolynomial(vararg pairs: Pair<Map<Symbol, UInt>, C>) : LabeledPolynomial<C> = LabeledPolynomial(*pairs, toCheckInput = true)
|
||||||
@Suppress("FunctionName")
|
@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)
|
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)
|
//context(A)
|
||||||
//public fun <C, A: Ring<C>> Symbol.asLabeledPolynomial() : LabeledPolynomial<C> = LabeledPolynomial<C>(mapOf(mapOf(this to 1u) to one))
|
//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> =
|
public override operator fun LabeledPolynomial<C>.plus(other: Int): LabeledPolynomial<C> =
|
||||||
if (other == 0) this
|
if (other == 0) this
|
||||||
else
|
else with(coefficients) {
|
||||||
LabeledPolynomial(
|
if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to other.asConstant()))
|
||||||
coefficients
|
else LabeledPolynomial<C>(
|
||||||
.toMutableMap()
|
toMutableMap()
|
||||||
.apply {
|
.apply {
|
||||||
val degs = emptyMap<Symbol, UInt>()
|
val degs = emptyMap<Symbol, UInt>()
|
||||||
|
|
||||||
val result = getOrElse(degs) { constantZero } + other
|
this[degs] = getOrElse(degs) { constantZero } + other
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
|
||||||
else this[degs] = result
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Returns difference between the polynomial and the integer represented as polynomial.
|
* 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> =
|
public override operator fun LabeledPolynomial<C>.minus(other: Int): LabeledPolynomial<C> =
|
||||||
if (other == 0) this
|
if (other == 0) this
|
||||||
else
|
else with(coefficients) {
|
||||||
LabeledPolynomial(
|
if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to (-other).asConstant()))
|
||||||
coefficients
|
else LabeledPolynomial<C>(
|
||||||
.toMutableMap()
|
toMutableMap()
|
||||||
.apply {
|
.apply {
|
||||||
val degs = emptyMap<Symbol, UInt>()
|
val degs = emptyMap<Symbol, UInt>()
|
||||||
|
|
||||||
val result = getOrElse(degs) { constantZero } - other
|
this[degs] = getOrElse(degs) { constantZero } - other
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
|
||||||
else this[degs] = result
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Returns product of the polynomial and the integer represented as polynomial.
|
* 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
|
if (other == 0) zero
|
||||||
else LabeledPolynomial(
|
else LabeledPolynomial(
|
||||||
coefficients
|
coefficients
|
||||||
.applyAndRemoveZeros {
|
.toMutableMap()
|
||||||
|
.apply {
|
||||||
for (degs in keys) this[degs] = this[degs]!! * other
|
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> =
|
public override operator fun Int.plus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||||
if (this == 0) other
|
if (this == 0) other
|
||||||
else
|
else with(other.coefficients) {
|
||||||
LabeledPolynomial(
|
if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to this@plus.asConstant()))
|
||||||
other.coefficients
|
else LabeledPolynomial<C>(
|
||||||
.toMutableMap()
|
toMutableMap()
|
||||||
.apply {
|
.apply {
|
||||||
val degs = emptyMap<Symbol, UInt>()
|
val degs = emptyMap<Symbol, UInt>()
|
||||||
|
|
||||||
val result = this@plus + getOrElse(degs) { constantZero }
|
this[degs] = this@plus + getOrElse(degs) { constantZero }
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
|
||||||
else this[degs] = result
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Returns difference between the integer represented as polynomial and the polynomial.
|
* 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> =
|
public override operator fun Int.minus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||||
if (this == 0) other
|
if (this == 0) other
|
||||||
else
|
else with(other.coefficients) {
|
||||||
LabeledPolynomial(
|
if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to this@minus.asConstant()))
|
||||||
other.coefficients
|
else LabeledPolynomial<C>(
|
||||||
.toMutableMap()
|
toMutableMap()
|
||||||
.apply {
|
.apply {
|
||||||
val degs = emptyMap<Symbol, UInt>()
|
val degs = emptyMap<Symbol, UInt>()
|
||||||
|
|
||||||
val result = this@minus - getOrElse(degs) { constantZero }
|
this[degs] = this@minus - getOrElse(degs) { constantZero }
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
|
||||||
else this[degs] = result
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Returns product of the integer represented as polynomial and the polynomial.
|
* 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
|
if (this == 0) zero
|
||||||
else LabeledPolynomial(
|
else LabeledPolynomial(
|
||||||
other.coefficients
|
other.coefficients
|
||||||
.applyAndRemoveZeros {
|
.toMutableMap()
|
||||||
|
.apply {
|
||||||
for (degs in keys) this[degs] = this@times * this[degs]!!
|
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 fun number(value: Int): LabeledPolynomial<C> = number(constantNumber(value))
|
||||||
|
|
||||||
public override operator fun C.plus(other: Symbol): LabeledPolynomial<C> =
|
public override operator fun C.plus(other: Symbol): LabeledPolynomial<C> =
|
||||||
if (isZero()) LabeledPolynomial<C>(mapOf(
|
LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(other to 1U) to constantOne,
|
|
||||||
))
|
|
||||||
else LabeledPolynomial<C>(mapOf(
|
|
||||||
mapOf(other to 1U) to constantOne,
|
mapOf(other to 1U) to constantOne,
|
||||||
emptyMap<Symbol, UInt>() to this@plus,
|
emptyMap<Symbol, UInt>() to this@plus,
|
||||||
))
|
))
|
||||||
public override operator fun C.minus(other: Symbol): LabeledPolynomial<C> =
|
public override operator fun C.minus(other: Symbol): LabeledPolynomial<C> =
|
||||||
if (isZero()) LabeledPolynomial<C>(mapOf(
|
LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(other to 1U) to -constantOne,
|
|
||||||
))
|
|
||||||
else LabeledPolynomial<C>(mapOf(
|
|
||||||
mapOf(other to 1U) to -constantOne,
|
mapOf(other to 1U) to -constantOne,
|
||||||
emptyMap<Symbol, UInt>() to this@minus,
|
emptyMap<Symbol, UInt>() to this@minus,
|
||||||
))
|
))
|
||||||
public override operator fun C.times(other: Symbol): LabeledPolynomial<C> =
|
public override operator fun C.times(other: Symbol): LabeledPolynomial<C> =
|
||||||
if (isZero()) zero
|
LabeledPolynomial<C>(mapOf(
|
||||||
else LabeledPolynomial<C>(mapOf(
|
|
||||||
mapOf(other to 1U) to this@times,
|
mapOf(other to 1U) to this@times,
|
||||||
))
|
))
|
||||||
|
|
||||||
public override operator fun Symbol.plus(other: C): LabeledPolynomial<C> =
|
public override operator fun Symbol.plus(other: C): LabeledPolynomial<C> =
|
||||||
if (other.isZero()) LabeledPolynomial<C>(mapOf(
|
LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(this@plus to 1U) to constantOne,
|
|
||||||
))
|
|
||||||
else LabeledPolynomial<C>(mapOf(
|
|
||||||
mapOf(this@plus to 1U) to constantOne,
|
mapOf(this@plus to 1U) to constantOne,
|
||||||
emptyMap<Symbol, UInt>() to other,
|
emptyMap<Symbol, UInt>() to other,
|
||||||
))
|
))
|
||||||
public override operator fun Symbol.minus(other: C): LabeledPolynomial<C> =
|
public override operator fun Symbol.minus(other: C): LabeledPolynomial<C> =
|
||||||
if (other.isZero()) LabeledPolynomial<C>(mapOf(
|
LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(this@minus to 1U) to -constantOne,
|
|
||||||
))
|
|
||||||
else LabeledPolynomial<C>(mapOf(
|
|
||||||
mapOf(this@minus to 1U) to -constantOne,
|
mapOf(this@minus to 1U) to -constantOne,
|
||||||
emptyMap<Symbol, UInt>() to other,
|
emptyMap<Symbol, UInt>() to other,
|
||||||
))
|
))
|
||||||
public override operator fun Symbol.times(other: C): LabeledPolynomial<C> =
|
public override operator fun Symbol.times(other: C): LabeledPolynomial<C> =
|
||||||
if (other.isZero()) zero
|
LabeledPolynomial<C>(mapOf(
|
||||||
else LabeledPolynomial<C>(mapOf(
|
|
||||||
mapOf(this@times to 1U) to other,
|
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.
|
* Returns sum of the constant represented as polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
override operator fun C.plus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
override operator fun C.plus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||||
if (this.isZero()) other
|
with(other.coefficients) {
|
||||||
else with(other.coefficients) {
|
|
||||||
if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to this@plus))
|
if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to this@plus))
|
||||||
else LabeledPolynomial<C>(
|
else LabeledPolynomial<C>(
|
||||||
toMutableMap()
|
toMutableMap()
|
||||||
.apply {
|
.apply {
|
||||||
val degs = emptyMap<Symbol, UInt>()
|
val degs = emptyMap<Symbol, UInt>()
|
||||||
|
|
||||||
val result = this@plus + getOrElse(degs) { constantZero }
|
this[degs] = this@plus + getOrElse(degs) { constantZero }
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
|
||||||
else this[degs] = result
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -369,8 +351,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
* Returns difference between the constant represented as polynomial and the polynomial.
|
* Returns difference between the constant represented as polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
override operator fun C.minus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
override operator fun C.minus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||||
if (this.isZero()) other
|
with(other.coefficients) {
|
||||||
else with(other.coefficients) {
|
|
||||||
if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to this@minus))
|
if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to this@minus))
|
||||||
else LabeledPolynomial<C>(
|
else LabeledPolynomial<C>(
|
||||||
toMutableMap()
|
toMutableMap()
|
||||||
@ -379,10 +360,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
|
|
||||||
val degs = emptyMap<Symbol, UInt>()
|
val degs = emptyMap<Symbol, UInt>()
|
||||||
|
|
||||||
val result = this@minus - getOrElse(degs) { constantZero }
|
this[degs] = this@minus - getOrElse(degs) { constantZero }
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
|
||||||
else this[degs] = result
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -390,10 +368,10 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
* Returns product of the constant represented as polynomial and the polynomial.
|
* Returns product of the constant represented as polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
override operator fun C.times(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
override operator fun C.times(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||||
if (this.isZero()) zero
|
LabeledPolynomial<C>(
|
||||||
else LabeledPolynomial<C>(
|
|
||||||
other.coefficients
|
other.coefficients
|
||||||
.applyAndRemoveZeros {
|
.toMutableMap()
|
||||||
|
.apply {
|
||||||
for (degs in keys) this[degs] = this@times * this[degs]!!
|
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.
|
* Returns sum of the constant represented as polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
override operator fun LabeledPolynomial<C>.plus(other: C): LabeledPolynomial<C> =
|
override operator fun LabeledPolynomial<C>.plus(other: C): LabeledPolynomial<C> =
|
||||||
if (other.isZero()) this
|
with(coefficients) {
|
||||||
else with(coefficients) {
|
|
||||||
if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to other))
|
if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to other))
|
||||||
else LabeledPolynomial<C>(
|
else LabeledPolynomial<C>(
|
||||||
toMutableMap()
|
toMutableMap()
|
||||||
.apply {
|
.apply {
|
||||||
val degs = emptyMap<Symbol, UInt>()
|
val degs = emptyMap<Symbol, UInt>()
|
||||||
|
|
||||||
val result = getOrElse(degs) { constantZero } + other
|
this[degs] = getOrElse(degs) { constantZero } + other
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
|
||||||
else this[degs] = result
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -421,8 +395,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
* Returns difference between the constant represented as polynomial and the polynomial.
|
* Returns difference between the constant represented as polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
override operator fun LabeledPolynomial<C>.minus(other: C): LabeledPolynomial<C> =
|
override operator fun LabeledPolynomial<C>.minus(other: C): LabeledPolynomial<C> =
|
||||||
if (other.isZero()) this
|
with(coefficients) {
|
||||||
else with(coefficients) {
|
|
||||||
if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to other))
|
if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to other))
|
||||||
else LabeledPolynomial<C>(
|
else LabeledPolynomial<C>(
|
||||||
toMutableMap()
|
toMutableMap()
|
||||||
@ -431,10 +404,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
|
|
||||||
val degs = emptyMap<Symbol, UInt>()
|
val degs = emptyMap<Symbol, UInt>()
|
||||||
|
|
||||||
val result = getOrElse(degs) { constantZero } - other
|
this[degs] = getOrElse(degs) { constantZero } - other
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
|
||||||
else this[degs] = result
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -442,10 +412,10 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
* Returns product of the constant represented as polynomial and the polynomial.
|
* Returns product of the constant represented as polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
override operator fun LabeledPolynomial<C>.times(other: C): LabeledPolynomial<C> =
|
override operator fun LabeledPolynomial<C>.times(other: C): LabeledPolynomial<C> =
|
||||||
if (other.isZero()) zero
|
LabeledPolynomial<C>(
|
||||||
else LabeledPolynomial<C>(
|
|
||||||
coefficients
|
coefficients
|
||||||
.applyAndRemoveZeros {
|
.toMutableMap()
|
||||||
|
.apply {
|
||||||
for (degs in keys) this[degs] = this[degs]!! * other
|
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.
|
* Converts the constant [value] to polynomial.
|
||||||
*/
|
*/
|
||||||
public override fun number(value: C): LabeledPolynomial<C> =
|
public override fun number(value: C): LabeledPolynomial<C> =
|
||||||
if (value == 0) zero
|
LabeledPolynomial(mapOf(emptyMap<Symbol, UInt>() to value))
|
||||||
else LabeledPolynomial(mapOf(emptyMap<Symbol, UInt>() to value))
|
|
||||||
|
|
||||||
public override operator fun Symbol.unaryPlus(): LabeledPolynomial<C> =
|
public override operator fun Symbol.unaryPlus(): LabeledPolynomial<C> =
|
||||||
LabeledPolynomial<C>(mapOf(
|
LabeledPolynomial<C>(mapOf(
|
||||||
@ -495,10 +464,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
.apply {
|
.apply {
|
||||||
val degs = mapOf(this@plus to 1U)
|
val degs = mapOf(this@plus to 1U)
|
||||||
|
|
||||||
val result = constantOne + getOrElse(degs) { constantZero }
|
this[degs] = constantOne + getOrElse(degs) { constantZero }
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
|
||||||
else this[degs] = result
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -512,10 +478,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
|
|
||||||
val degs = mapOf(this@minus to 1U)
|
val degs = mapOf(this@minus to 1U)
|
||||||
|
|
||||||
val result = constantOne - getOrElse(degs) { constantZero }
|
this[degs] = constantOne - getOrElse(degs) { constantZero }
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
|
||||||
else this[degs] = result
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -533,10 +496,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
.apply {
|
.apply {
|
||||||
val degs = mapOf(other to 1U)
|
val degs = mapOf(other to 1U)
|
||||||
|
|
||||||
val result = constantOne + getOrElse(degs) { constantZero }
|
this[degs] = constantOne + getOrElse(degs) { constantZero }
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
|
||||||
else this[degs] = result
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -548,10 +508,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
.apply {
|
.apply {
|
||||||
val degs = mapOf(other to 1U)
|
val degs = mapOf(other to 1U)
|
||||||
|
|
||||||
val result = constantOne - getOrElse(degs) { constantZero }
|
this[degs] = constantOne - getOrElse(degs) { constantZero }
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
|
||||||
else this[degs] = result
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -573,7 +530,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
*/
|
*/
|
||||||
override operator fun LabeledPolynomial<C>.plus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
override operator fun LabeledPolynomial<C>.plus(other: LabeledPolynomial<C>): 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) { it.value }
|
||||||
other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value }
|
other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value }
|
||||||
}
|
}
|
||||||
@ -583,7 +540,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
*/
|
*/
|
||||||
override operator fun LabeledPolynomial<C>.minus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
override operator fun LabeledPolynomial<C>.minus(other: LabeledPolynomial<C>): 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) { it.value }
|
||||||
other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value }
|
other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value }
|
||||||
}
|
}
|
||||||
@ -592,11 +549,8 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
* Returns product of the polynomials.
|
* Returns product of the polynomials.
|
||||||
*/
|
*/
|
||||||
override operator fun LabeledPolynomial<C>.times(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
override operator fun LabeledPolynomial<C>.times(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||||
when {
|
LabeledPolynomial<C>(
|
||||||
isZero() -> zero
|
buildMap(coefficients.size * other.coefficients.size) {
|
||||||
other.isZero() -> zero
|
|
||||||
else -> LabeledPolynomial<C>(
|
|
||||||
buildCoefficients(coefficients.size * other.coefficients.size) {
|
|
||||||
for ((degs1, c1) in coefficients) for ((degs2, c2) in other.coefficients) {
|
for ((degs1, c1) in coefficients) for ((degs2, c2) in other.coefficients) {
|
||||||
val degs = degs1.toMutableMap()
|
val degs = degs1.toMutableMap()
|
||||||
degs2.mapValuesTo(degs) { (variable, deg) -> degs.getOrElse(variable) { 0u } + deg }
|
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).
|
* 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))
|
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
|
* Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is
|
||||||
* zero, degree is -1.
|
* zero, degree is -1.
|
||||||
*/
|
*/
|
||||||
override val LabeledPolynomial<C>.degree: Int
|
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
|
* Map that associates variables (that appear in the polynomial in positive exponents) with their most exponents
|
||||||
* in which they are appeared in the polynomial.
|
* 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>
|
public override val LabeledPolynomial<C>.degrees: Map<Symbol, UInt>
|
||||||
get() =
|
get() =
|
||||||
buildMap {
|
buildMap {
|
||||||
coefficients.entries.forEach { (degs, c) ->
|
coefficients.entries.forEach { (degs, _) ->
|
||||||
if (c.isNotZero()) degs.mapValuesTo(this) { (variable, deg) ->
|
degs.mapValuesTo(this) { (variable, deg) ->
|
||||||
max(getOrElse(variable) { 0u }, 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].
|
* Counts degree of the polynomial by the specified [variable].
|
||||||
*/
|
*/
|
||||||
public override fun LabeledPolynomial<C>.degreeBy(variable: Symbol): UInt =
|
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].
|
* Counts degree of the polynomial by the specified [variables].
|
||||||
*/
|
*/
|
||||||
public override fun LabeledPolynomial<C>.degreeBy(variables: Collection<Symbol>): UInt =
|
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.
|
* Set of all variables that appear in the polynomial in positive exponents.
|
||||||
*/
|
*/
|
||||||
public override val LabeledPolynomial<C>.variables: Set<Symbol>
|
public override val LabeledPolynomial<C>.variables: Set<Symbol>
|
||||||
get() =
|
get() =
|
||||||
buildSet {
|
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.
|
* Count of all variables that appear in the polynomial in positive exponents.
|
||||||
*/
|
*/
|
||||||
public override val LabeledPolynomial<C>.countOfVariables: Int get() = variables.size
|
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")
|
// @Suppress("NOTHING_TO_INLINE")
|
||||||
// public inline fun LabeledPolynomial<C>.substitute(argument: Map<Symbol, C>): LabeledPolynomial<C> = this.substitute(ring, argument)
|
// public inline fun LabeledPolynomial<C>.substitute(argument: Map<Symbol, C>): LabeledPolynomial<C> = this.substitute(ring, argument)
|
||||||
// @Suppress("NOTHING_TO_INLINE")
|
// @Suppress("NOTHING_TO_INLINE")
|
||||||
@ -719,33 +632,4 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
// @Suppress("NOTHING_TO_INLINE")
|
// @Suppress("NOTHING_TO_INLINE")
|
||||||
// @JvmName("invokePolynomial")
|
// @JvmName("invokePolynomial")
|
||||||
// public inline operator fun LabeledPolynomial<C>.invoke(argument: Map<Symbol, LabeledPolynomial<C>>): LabeledPolynomial<C> = this.substitute(ring, argument)
|
// 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
|
// 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")
|
@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> =
|
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")
|
LabeledRationalFunction<C>(
|
||||||
else LabeledRationalFunction<C>(
|
LabeledPolynomial(numeratorCoefficients, toCheckInput = true),
|
||||||
LabeledPolynomial(numeratorCoefficients),
|
LabeledPolynomial(denominatorCoefficients, toCheckInput = true)
|
||||||
LabeledPolynomial(denominatorCoefficients)
|
|
||||||
)
|
)
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
public fun <C, A: Ring<C>> A.LabeledRationalFunction(numeratorCoefficients: Map<Map<Symbol, UInt>, C>, denominatorCoefficients: Map<Map<Symbol, UInt>, C>): LabeledRationalFunction<C> =
|
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")
|
LabeledRationalFunction<C>(
|
||||||
else LabeledRationalFunction<C>(
|
LabeledPolynomial(numeratorCoefficients, toCheckInput = true),
|
||||||
LabeledPolynomial(numeratorCoefficients),
|
LabeledPolynomial(denominatorCoefficients, toCheckInput = true)
|
||||||
LabeledPolynomial(denominatorCoefficients)
|
|
||||||
)
|
)
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
public fun <C, A: Ring<C>> LabeledRationalFunctionSpace<C, A>.LabeledRationalFunction(numerator: LabeledPolynomial<C>): LabeledRationalFunction<C> =
|
public fun <C, A: Ring<C>> LabeledRationalFunctionSpace<C, A>.LabeledRationalFunction(numerator: LabeledPolynomial<C>): LabeledRationalFunction<C> =
|
||||||
LabeledRationalFunction<C>(numerator, polynomialOne)
|
LabeledRationalFunction<C>(numerator, polynomialOne)
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
public fun <C, A: Ring<C>> A.LabeledRationalFunction(numerator: LabeledPolynomial<C>): LabeledRationalFunction<C> =
|
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")
|
@Suppress("FunctionName")
|
||||||
public fun <C, A: Ring<C>> LabeledRationalFunctionSpace<C, A>.LabeledRationalFunction(numeratorCoefficients: Map<Map<Symbol, UInt>, C>): LabeledRationalFunction<C> =
|
public fun <C, A: Ring<C>> LabeledRationalFunctionSpace<C, A>.LabeledRationalFunction(numeratorCoefficients: Map<Map<Symbol, UInt>, C>): LabeledRationalFunction<C> =
|
||||||
LabeledRationalFunction<C>(
|
LabeledRationalFunction<C>(
|
||||||
LabeledPolynomial(numeratorCoefficients),
|
LabeledPolynomial(numeratorCoefficients, toCheckInput = true),
|
||||||
polynomialOne
|
polynomialOne
|
||||||
)
|
)
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
public fun <C, A: Ring<C>> A.LabeledRationalFunction(numeratorCoefficients: Map<Map<Symbol, UInt>, C>): LabeledRationalFunction<C> =
|
public fun <C, A: Ring<C>> A.LabeledRationalFunction(numeratorCoefficients: Map<Map<Symbol, UInt>, C>): LabeledRationalFunction<C> =
|
||||||
LabeledRationalFunction<C>(
|
LabeledRationalFunction<C>(
|
||||||
LabeledPolynomial(numeratorCoefficients),
|
LabeledPolynomial(numeratorCoefficients, toCheckInput = true),
|
||||||
LabeledPolynomial(mapOf(emptyMap<Symbol, UInt>() to one))
|
LabeledPolynomial(mapOf(emptyMap<Symbol, UInt>() to one), toCheckInput = false)
|
||||||
)
|
)
|
||||||
|
|
||||||
public class LabeledRationalFunctionSpace<C, A: Ring<C>>(
|
public class LabeledRationalFunctionSpace<C, A: Ring<C>>(
|
||||||
@ -82,38 +72,16 @@ public class LabeledRationalFunctionSpace<C, A: Ring<C>>(
|
|||||||
numerator: LabeledPolynomial<C>,
|
numerator: LabeledPolynomial<C>,
|
||||||
denominator: LabeledPolynomial<C>
|
denominator: LabeledPolynomial<C>
|
||||||
): LabeledRationalFunction<C> =
|
): LabeledRationalFunction<C> =
|
||||||
LabeledRationalFunction(numerator, denominator)
|
LabeledRationalFunction<C>(numerator, denominator)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instance of zero rational function (zero of the rational functions ring).
|
* 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).
|
* Instance of unit polynomial (unit of the rational functions ring).
|
||||||
*/
|
*/
|
||||||
public override val one: LabeledRationalFunction<C> = LabeledRationalFunction(polynomialOne, polynomialOne)
|
public override val one: LabeledRationalFunction<C> = LabeledRationalFunction<C>(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
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Разобрать
|
// TODO: Разобрать
|
||||||
|
|
||||||
|
@ -91,13 +91,9 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
|
|||||||
.toMutableList()
|
.toMutableList()
|
||||||
.apply {
|
.apply {
|
||||||
val result = getOrElse(0) { constantZero } + other
|
val result = getOrElse(0) { constantZero } + other
|
||||||
val isResultZero = result.isZero()
|
|
||||||
|
|
||||||
when {
|
if(size == 0) add(result)
|
||||||
size == 0 && !isResultZero -> add(result)
|
else this[0] = result
|
||||||
size > 1 || !isResultZero -> this[0] = result
|
|
||||||
else -> clear()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
@ -113,13 +109,9 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
|
|||||||
.toMutableList()
|
.toMutableList()
|
||||||
.apply {
|
.apply {
|
||||||
val result = getOrElse(0) { constantZero } - other
|
val result = getOrElse(0) { constantZero } - other
|
||||||
val isResultZero = result.isZero()
|
|
||||||
|
|
||||||
when {
|
if(size == 0) add(result)
|
||||||
size == 0 && !isResultZero -> add(result)
|
else this[0] = result
|
||||||
size > 1 || !isResultZero -> this[0] = result
|
|
||||||
else -> clear()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
@ -131,7 +123,8 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
|
|||||||
if (other == 0) zero
|
if (other == 0) zero
|
||||||
else ListPolynomial(
|
else ListPolynomial(
|
||||||
coefficients
|
coefficients
|
||||||
.applyAndRemoveZeros {
|
.toMutableList()
|
||||||
|
.apply {
|
||||||
for (deg in indices) this[deg] = this[deg] * other
|
for (deg in indices) this[deg] = this[deg] * other
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -149,13 +142,9 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
|
|||||||
.toMutableList()
|
.toMutableList()
|
||||||
.apply {
|
.apply {
|
||||||
val result = this@plus + getOrElse(0) { constantZero }
|
val result = this@plus + getOrElse(0) { constantZero }
|
||||||
val isResultZero = result.isZero()
|
|
||||||
|
|
||||||
when {
|
if(size == 0) add(result)
|
||||||
size == 0 && !isResultZero -> add(result)
|
else this[0] = result
|
||||||
size > 1 || !isResultZero -> this[0] = result
|
|
||||||
else -> clear()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
@ -173,13 +162,9 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
|
|||||||
forEachIndexed { index, c -> if (index != 0) this[index] = -c }
|
forEachIndexed { index, c -> if (index != 0) this[index] = -c }
|
||||||
|
|
||||||
val result = this@minus - getOrElse(0) { constantZero }
|
val result = this@minus - getOrElse(0) { constantZero }
|
||||||
val isResultZero = result.isZero()
|
|
||||||
|
|
||||||
when {
|
if(size == 0) add(result)
|
||||||
size == 0 && !isResultZero -> add(result)
|
else this[0] = result
|
||||||
size > 1 || !isResultZero -> this[0] = result
|
|
||||||
else -> clear()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
@ -191,7 +176,8 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
|
|||||||
if (this == 0) zero
|
if (this == 0) zero
|
||||||
else ListPolynomial(
|
else ListPolynomial(
|
||||||
other.coefficients
|
other.coefficients
|
||||||
.applyAndRemoveZeros {
|
.toMutableList()
|
||||||
|
.apply {
|
||||||
for (deg in indices) this[deg] = this@times * this[deg]
|
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.
|
* Returns sum of the constant represented as polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
public override operator fun C.plus(other: ListPolynomial<C>): ListPolynomial<C> =
|
public override operator fun C.plus(other: ListPolynomial<C>): ListPolynomial<C> =
|
||||||
if (this.isZero()) other
|
with(other.coefficients) {
|
||||||
else with(other.coefficients) {
|
|
||||||
if (isEmpty()) ListPolynomial(listOf(this@plus))
|
if (isEmpty()) ListPolynomial(listOf(this@plus))
|
||||||
else ListPolynomial(
|
else ListPolynomial(
|
||||||
toMutableList()
|
toMutableList()
|
||||||
.apply {
|
.apply {
|
||||||
val result = if (size == 0) this@plus else this@plus + get(0)
|
val result = if (size == 0) this@plus else this@plus + get(0)
|
||||||
val isResultZero = result.isZero()
|
|
||||||
|
|
||||||
when {
|
if(size == 0) add(result)
|
||||||
size == 0 && !isResultZero -> add(result)
|
else this[0] = result
|
||||||
size > 1 || !isResultZero -> this[0] = result
|
|
||||||
else -> clear()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -226,8 +207,7 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
|
|||||||
* Returns difference between the constant represented as polynomial and the polynomial.
|
* Returns difference between the constant represented as polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
public override operator fun C.minus(other: ListPolynomial<C>): ListPolynomial<C> =
|
public override operator fun C.minus(other: ListPolynomial<C>): ListPolynomial<C> =
|
||||||
if (this.isZero()) other
|
with(other.coefficients) {
|
||||||
else with(other.coefficients) {
|
|
||||||
if (isEmpty()) ListPolynomial(listOf(this@minus))
|
if (isEmpty()) ListPolynomial(listOf(this@minus))
|
||||||
else ListPolynomial(
|
else ListPolynomial(
|
||||||
toMutableList()
|
toMutableList()
|
||||||
@ -235,13 +215,9 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
|
|||||||
forEachIndexed { index, c -> if (index != 0) this[index] = -c }
|
forEachIndexed { index, c -> if (index != 0) this[index] = -c }
|
||||||
|
|
||||||
val result = if (size == 0) this@minus else this@minus - get(0)
|
val result = if (size == 0) this@minus else this@minus - get(0)
|
||||||
val isResultZero = result.isZero()
|
|
||||||
|
|
||||||
when {
|
if(size == 0) add(result)
|
||||||
size == 0 && !isResultZero -> add(result)
|
else this[0] = result
|
||||||
size > 1 || !isResultZero -> this[0] = result
|
|
||||||
else -> clear()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -249,10 +225,10 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
|
|||||||
* Returns product of the constant represented as polynomial and the polynomial.
|
* Returns product of the constant represented as polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
public override operator fun C.times(other: ListPolynomial<C>): ListPolynomial<C> =
|
public override operator fun C.times(other: ListPolynomial<C>): ListPolynomial<C> =
|
||||||
if (this.isZero()) other
|
ListPolynomial(
|
||||||
else ListPolynomial(
|
|
||||||
other.coefficients
|
other.coefficients
|
||||||
.applyAndRemoveZeros {
|
.toMutableList()
|
||||||
|
.apply {
|
||||||
for (deg in indices) this[deg] = this@times * this[deg]
|
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.
|
* Returns sum of the constant represented as polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
public override operator fun ListPolynomial<C>.plus(other: C): ListPolynomial<C> =
|
public override operator fun ListPolynomial<C>.plus(other: C): ListPolynomial<C> =
|
||||||
if (other.isZero()) this
|
with(coefficients) {
|
||||||
else with(coefficients) {
|
|
||||||
if (isEmpty()) ListPolynomial(listOf(other))
|
if (isEmpty()) ListPolynomial(listOf(other))
|
||||||
else ListPolynomial(
|
else ListPolynomial(
|
||||||
toMutableList()
|
toMutableList()
|
||||||
.apply {
|
.apply {
|
||||||
val result = if (size == 0) other else get(0) + other
|
val result = if (size == 0) other else get(0) + other
|
||||||
val isResultZero = result.isZero()
|
|
||||||
|
|
||||||
when {
|
if(size == 0) add(result)
|
||||||
size == 0 && !isResultZero -> add(result)
|
else this[0] = result
|
||||||
size > 1 || !isResultZero -> this[0] = result
|
|
||||||
else -> clear()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -282,20 +253,15 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
|
|||||||
* Returns difference between the constant represented as polynomial and the polynomial.
|
* Returns difference between the constant represented as polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
public override operator fun ListPolynomial<C>.minus(other: C): ListPolynomial<C> =
|
public override operator fun ListPolynomial<C>.minus(other: C): ListPolynomial<C> =
|
||||||
if (other.isZero()) this
|
with(coefficients) {
|
||||||
else with(coefficients) {
|
|
||||||
if (isEmpty()) ListPolynomial(listOf(-other))
|
if (isEmpty()) ListPolynomial(listOf(-other))
|
||||||
else ListPolynomial(
|
else ListPolynomial(
|
||||||
toMutableList()
|
toMutableList()
|
||||||
.apply {
|
.apply {
|
||||||
val result = if (size == 0) other else get(0) - other
|
val result = if (size == 0) other else get(0) - other
|
||||||
val isResultZero = result.isZero()
|
|
||||||
|
|
||||||
when {
|
if(size == 0) add(result)
|
||||||
size == 0 && !isResultZero -> add(result)
|
else this[0] = result
|
||||||
size > 1 || !isResultZero -> this[0] = result
|
|
||||||
else -> clear()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -303,10 +269,10 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
|
|||||||
* Returns product of the constant represented as polynomial and the polynomial.
|
* Returns product of the constant represented as polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
public override operator fun ListPolynomial<C>.times(other: C): ListPolynomial<C> =
|
public override operator fun ListPolynomial<C>.times(other: C): ListPolynomial<C> =
|
||||||
if (other.isZero()) this
|
ListPolynomial(
|
||||||
else ListPolynomial(
|
|
||||||
coefficients
|
coefficients
|
||||||
.applyAndRemoveZeros {
|
.toMutableList()
|
||||||
|
.apply {
|
||||||
for (deg in indices) this[deg] = this[deg] * other
|
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.
|
* Converts the constant [value] to polynomial.
|
||||||
*/
|
*/
|
||||||
public override fun number(value: C): ListPolynomial<C> =
|
public override fun number(value: C): ListPolynomial<C> = ListPolynomial(value)
|
||||||
if (value.isZero()) zero
|
|
||||||
else ListPolynomial(value)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns negation of the polynomial.
|
* Returns negation of the polynomial.
|
||||||
@ -330,7 +294,7 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
|
|||||||
val thisDegree = degree
|
val thisDegree = degree
|
||||||
val otherDegree = other.degree
|
val otherDegree = other.degree
|
||||||
return ListPolynomial(
|
return ListPolynomial(
|
||||||
Coefficients(max(thisDegree, otherDegree) + 1) {
|
List(max(thisDegree, otherDegree) + 1) {
|
||||||
when {
|
when {
|
||||||
it > thisDegree -> other.coefficients[it]
|
it > thisDegree -> other.coefficients[it]
|
||||||
it > otherDegree -> coefficients[it]
|
it > otherDegree -> coefficients[it]
|
||||||
@ -346,7 +310,7 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
|
|||||||
val thisDegree = degree
|
val thisDegree = degree
|
||||||
val otherDegree = other.degree
|
val otherDegree = other.degree
|
||||||
return ListPolynomial(
|
return ListPolynomial(
|
||||||
Coefficients(max(thisDegree, otherDegree) + 1) {
|
List(max(thisDegree, otherDegree) + 1) {
|
||||||
when {
|
when {
|
||||||
it > thisDegree -> -other.coefficients[it]
|
it > thisDegree -> -other.coefficients[it]
|
||||||
it > otherDegree -> 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> {
|
public override operator fun ListPolynomial<C>.times(other: ListPolynomial<C>): ListPolynomial<C> {
|
||||||
val thisDegree = degree
|
val thisDegree = degree
|
||||||
val otherDegree = other.degree
|
val otherDegree = other.degree
|
||||||
return when {
|
return ListPolynomial(
|
||||||
thisDegree == -1 -> zero
|
List(thisDegree + otherDegree + 1) { d ->
|
||||||
otherDegree == -1 -> zero
|
|
||||||
else ->
|
|
||||||
ListPolynomial(
|
|
||||||
Coefficients(thisDegree + otherDegree + 1) { d ->
|
|
||||||
(max(0, d - otherDegree)..min(thisDegree, d))
|
(max(0, d - otherDegree)..min(thisDegree, d))
|
||||||
.map { coefficients[it] * other.coefficients[d - it] }
|
.map { coefficients[it] * other.coefficients[d - it] }
|
||||||
.reduce { acc, rational -> acc + rational }
|
.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).
|
* 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))
|
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
|
* Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is
|
||||||
* zero, degree is -1.
|
* zero, degree is -1.
|
||||||
*/
|
*/
|
||||||
public override val ListPolynomial<C>.degree: Int get() = coefficients.indexOfLast { it != constantZero }
|
public override val ListPolynomial<C>.degree: Int get() = coefficients.lastIndex
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
public inline fun ListPolynomial<C>.substitute(argument: C): C = this.substitute(ring, argument)
|
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)
|
public inline operator fun ListPolynomial<C>.invoke(argument: C): C = this.substitute(ring, argument)
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
public inline operator fun ListPolynomial<C>.invoke(argument: ListPolynomial<C>): ListPolynomial<C> = this.substitute(ring, argument)
|
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
|
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 numerator: ListPolynomial<C>,
|
||||||
public override val denominator: ListPolynomial<C>
|
public override val denominator: ListPolynomial<C>
|
||||||
) : RationalFunction<C, 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
|
// 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")
|
@Suppress("FunctionName")
|
||||||
public fun <C, A: Ring<C>> ListRationalFunctionSpace<C, A>.ListRationalFunction(numeratorCoefficients: List<C>, denominatorCoefficients: List<C>, reverse: Boolean = false): ListRationalFunction<C> =
|
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")
|
ListRationalFunction<C>(
|
||||||
else ListRationalFunction<C>(
|
|
||||||
ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ),
|
ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ),
|
||||||
ListPolynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } )
|
ListPolynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } )
|
||||||
)
|
)
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
public fun <C, A: Ring<C>> A.ListRationalFunction(numeratorCoefficients: List<C>, denominatorCoefficients: List<C>, reverse: Boolean = false): ListRationalFunction<C> =
|
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")
|
ListRationalFunction<C>(
|
||||||
else ListRationalFunction<C>(
|
|
||||||
ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ),
|
ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ),
|
||||||
ListPolynomial( with(denominatorCoefficients) { 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")
|
@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)
|
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")
|
@Suppress("FunctionName")
|
||||||
internal fun <C, A: Ring<C>> A.NumberedPolynomial(coefs: Map<List<UInt>, C>, toCheckInput: Boolean = true) : NumberedPolynomial<C> {
|
internal fun <C, A: Ring<C>> A.NumberedPolynomial(coefs: Map<List<UInt>, C>, toCheckInput: Boolean = true) : NumberedPolynomial<C> {
|
||||||
if (!toCheckInput) return NumberedPolynomial<C>(coefs)
|
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
|
fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value
|
||||||
}
|
}
|
||||||
|
|
||||||
return NumberedPolynomial<C>(
|
return NumberedPolynomial<C>(fixedCoefs)
|
||||||
fixedCoefs.filterValues { it != zero }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("FunctionName", "NOTHING_TO_INLINE")
|
@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)
|
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")
|
@Suppress("FunctionName")
|
||||||
internal fun <C, A: Ring<C>> A.NumberedPolynomial(pairs: Collection<Pair<List<UInt>, C>>, toCheckInput: Boolean = true) : NumberedPolynomial<C> {
|
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())
|
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
|
fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value
|
||||||
}
|
}
|
||||||
|
|
||||||
return NumberedPolynomial<C>(
|
return NumberedPolynomial<C>(fixedCoefs)
|
||||||
fixedCoefs.filterValues { it != zero }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("FunctionName", "NOTHING_TO_INLINE")
|
@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)
|
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")
|
@Suppress("FunctionName")
|
||||||
internal fun <C, A: Ring<C>> A.NumberedPolynomial(vararg pairs: Pair<List<UInt>, C>, toCheckInput: Boolean = true) : NumberedPolynomial<C> {
|
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())
|
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
|
fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value
|
||||||
}
|
}
|
||||||
|
|
||||||
return NumberedPolynomial<C>(
|
return NumberedPolynomial<C>(fixedCoefs)
|
||||||
fixedCoefs.filterValues { it != zero }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
public fun <C, A: Ring<C>> A.NumberedPolynomial(coefs: Map<List<UInt>, C>) : NumberedPolynomial<C> = NumberedPolynomial(coefs, toCheckInput = true)
|
public fun <C, A: Ring<C>> A.NumberedPolynomial(coefs: Map<List<UInt>, C>) : NumberedPolynomial<C> = NumberedPolynomial(coefs, toCheckInput = true)
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
public fun <C, A: Ring<C>> NumberedPolynomialSpace<C, A>.NumberedPolynomial(coefs: Map<List<UInt>, C>) : NumberedPolynomial<C> = NumberedPolynomial(coefs, toCheckInput = true)
|
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")
|
@Suppress("FunctionName")
|
||||||
public fun <C, A: Ring<C>> A.NumberedPolynomial(pairs: Collection<Pair<List<UInt>, C>>) : NumberedPolynomial<C> = NumberedPolynomial(pairs, toCheckInput = true)
|
public fun <C, A: Ring<C>> A.NumberedPolynomial(pairs: Collection<Pair<List<UInt>, C>>) : NumberedPolynomial<C> = NumberedPolynomial(pairs, toCheckInput = true)
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
public fun <C, A: Ring<C>> NumberedPolynomialSpace<C, A>.NumberedPolynomial(pairs: Collection<Pair<List<UInt>, C>>) : NumberedPolynomial<C> = NumberedPolynomial(pairs, toCheckInput = true)
|
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")
|
@Suppress("FunctionName")
|
||||||
public fun <C, A: Ring<C>> A.NumberedPolynomial(vararg pairs: Pair<List<UInt>, C>) : NumberedPolynomial<C> = NumberedPolynomial(*pairs, toCheckInput = true)
|
public fun <C, A: Ring<C>> A.NumberedPolynomial(vararg pairs: Pair<List<UInt>, C>) : NumberedPolynomial<C> = NumberedPolynomial(*pairs, toCheckInput = true)
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
public fun <C, A: Ring<C>> NumberedPolynomialSpace<C, A>.NumberedPolynomial(vararg pairs: Pair<List<UInt>, C>) : NumberedPolynomial<C> = NumberedPolynomial(*pairs, toCheckInput = true)
|
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)
|
//context(A)
|
||||||
//public fun <C, A: Ring<C>> Symbol.asNumberedPolynomial() : NumberedPolynomial<C> = NumberedPolynomial<C>(mapOf(mapOf(this to 1u) to one))
|
//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 {
|
.apply {
|
||||||
val degs = emptyList<UInt>()
|
val degs = emptyList<UInt>()
|
||||||
|
|
||||||
val result = getOrElse(degs) { constantZero } + other
|
this[degs] = getOrElse(degs) { constantZero } + other
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
|
||||||
else this[degs] = result
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
@ -231,10 +234,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
.apply {
|
.apply {
|
||||||
val degs = emptyList<UInt>()
|
val degs = emptyList<UInt>()
|
||||||
|
|
||||||
val result = getOrElse(degs) { constantZero } - other
|
this[degs] = getOrElse(degs) { constantZero } - other
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
|
||||||
else this[degs] = result
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
@ -246,7 +246,8 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
if (other == 0) zero
|
if (other == 0) zero
|
||||||
else NumberedPolynomial<C>(
|
else NumberedPolynomial<C>(
|
||||||
coefficients
|
coefficients
|
||||||
.applyAndRemoveZeros {
|
.toMutableMap()
|
||||||
|
.apply {
|
||||||
for (degs in keys) this[degs] = this[degs]!! * other
|
for (degs in keys) this[degs] = this[degs]!! * other
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -265,10 +266,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
.apply {
|
.apply {
|
||||||
val degs = emptyList<UInt>()
|
val degs = emptyList<UInt>()
|
||||||
|
|
||||||
val result = this@plus + getOrElse(degs) { constantZero }
|
this[degs] = this@plus + getOrElse(degs) { constantZero }
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
|
||||||
else this[degs] = result
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
@ -285,10 +283,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
.apply {
|
.apply {
|
||||||
val degs = emptyList<UInt>()
|
val degs = emptyList<UInt>()
|
||||||
|
|
||||||
val result = this@minus - getOrElse(degs) { constantZero }
|
this[degs] = this@minus - getOrElse(degs) { constantZero }
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
|
||||||
else this[degs] = result
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
@ -300,7 +295,8 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
if (this == 0) zero
|
if (this == 0) zero
|
||||||
else NumberedPolynomial(
|
else NumberedPolynomial(
|
||||||
other.coefficients
|
other.coefficients
|
||||||
.applyAndRemoveZeros {
|
.toMutableMap()
|
||||||
|
.apply {
|
||||||
for (degs in keys) this[degs] = this@times * this[degs]!!
|
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.
|
* Returns sum of the constant represented as polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
override operator fun C.plus(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
override operator fun C.plus(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
||||||
if (this.isZero()) other
|
with(other.coefficients) {
|
||||||
else with(other.coefficients) {
|
|
||||||
if (isEmpty()) NumberedPolynomial<C>(mapOf(emptyList<UInt>() to this@plus))
|
if (isEmpty()) NumberedPolynomial<C>(mapOf(emptyList<UInt>() to this@plus))
|
||||||
else NumberedPolynomial<C>(
|
else NumberedPolynomial<C>(
|
||||||
toMutableMap()
|
toMutableMap()
|
||||||
.apply {
|
.apply {
|
||||||
val degs = emptyList<UInt>()
|
val degs = emptyList<UInt>()
|
||||||
|
|
||||||
val result = this@plus + getOrElse(degs) { constantZero }
|
this[degs] = this@plus + getOrElse(degs) { constantZero }
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
|
||||||
else this[degs] = result
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -333,8 +325,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
* Returns difference between the constant represented as polynomial and the polynomial.
|
* Returns difference between the constant represented as polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
override operator fun C.minus(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
override operator fun C.minus(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
||||||
if (this.isZero()) -other
|
with(other.coefficients) {
|
||||||
else with(other.coefficients) {
|
|
||||||
if (isEmpty()) NumberedPolynomial<C>(mapOf(emptyList<UInt>() to this@minus))
|
if (isEmpty()) NumberedPolynomial<C>(mapOf(emptyList<UInt>() to this@minus))
|
||||||
else NumberedPolynomial<C>(
|
else NumberedPolynomial<C>(
|
||||||
toMutableMap()
|
toMutableMap()
|
||||||
@ -343,10 +334,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
|
|
||||||
val degs = emptyList<UInt>()
|
val degs = emptyList<UInt>()
|
||||||
|
|
||||||
val result = this@minus - getOrElse(degs) { constantZero }
|
this[degs] = this@minus - getOrElse(degs) { constantZero }
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
|
||||||
else this[degs] = result
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -354,10 +342,10 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
* Returns product of the constant represented as polynomial and the polynomial.
|
* Returns product of the constant represented as polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
override operator fun C.times(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
override operator fun C.times(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
||||||
if (this.isZero()) zero
|
NumberedPolynomial<C>(
|
||||||
else NumberedPolynomial<C>(
|
|
||||||
other.coefficients
|
other.coefficients
|
||||||
.applyAndRemoveZeros {
|
.toMutableMap()
|
||||||
|
.apply {
|
||||||
for (degs in keys) this[degs] = this@times * this[degs]!!
|
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.
|
* Returns sum of the constant represented as polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
override operator fun NumberedPolynomial<C>.plus(other: C): NumberedPolynomial<C> =
|
override operator fun NumberedPolynomial<C>.plus(other: C): NumberedPolynomial<C> =
|
||||||
if (other.isZero()) this
|
with(coefficients) {
|
||||||
else with(coefficients) {
|
|
||||||
if (isEmpty()) NumberedPolynomial<C>(mapOf(emptyList<UInt>() to other))
|
if (isEmpty()) NumberedPolynomial<C>(mapOf(emptyList<UInt>() to other))
|
||||||
else NumberedPolynomial<C>(
|
else NumberedPolynomial<C>(
|
||||||
toMutableMap()
|
toMutableMap()
|
||||||
.apply {
|
.apply {
|
||||||
val degs = emptyList<UInt>()
|
val degs = emptyList<UInt>()
|
||||||
|
|
||||||
val result = getOrElse(degs) { constantZero } + other
|
this[degs] = getOrElse(degs) { constantZero } + other
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
|
||||||
else this[degs] = result
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -385,18 +369,14 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
* Returns difference between the constant represented as polynomial and the polynomial.
|
* Returns difference between the constant represented as polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
override operator fun NumberedPolynomial<C>.minus(other: C): NumberedPolynomial<C> =
|
override operator fun NumberedPolynomial<C>.minus(other: C): NumberedPolynomial<C> =
|
||||||
if (other.isZero()) this
|
with(coefficients) {
|
||||||
else with(coefficients) {
|
|
||||||
if (isEmpty()) NumberedPolynomial<C>(mapOf(emptyList<UInt>() to other))
|
if (isEmpty()) NumberedPolynomial<C>(mapOf(emptyList<UInt>() to other))
|
||||||
else NumberedPolynomial<C>(
|
else NumberedPolynomial<C>(
|
||||||
toMutableMap()
|
toMutableMap()
|
||||||
.apply {
|
.apply {
|
||||||
val degs = emptyList<UInt>()
|
val degs = emptyList<UInt>()
|
||||||
|
|
||||||
val result = getOrElse(degs) { constantZero } - other
|
this[degs] = getOrElse(degs) { constantZero } - other
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
|
||||||
else this[degs] = result
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -404,10 +384,10 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
* Returns product of the constant represented as polynomial and the polynomial.
|
* Returns product of the constant represented as polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
override operator fun NumberedPolynomial<C>.times(other: C): NumberedPolynomial<C> =
|
override operator fun NumberedPolynomial<C>.times(other: C): NumberedPolynomial<C> =
|
||||||
if (other.isZero()) zero
|
NumberedPolynomial<C>(
|
||||||
else NumberedPolynomial<C>(
|
|
||||||
coefficients
|
coefficients
|
||||||
.applyAndRemoveZeros {
|
.toMutableMap()
|
||||||
|
.apply {
|
||||||
for (degs in keys) this[degs] = this[degs]!! * other
|
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.
|
* Converts the constant [value] to polynomial.
|
||||||
*/
|
*/
|
||||||
public override fun number(value: C): NumberedPolynomial<C> =
|
public override fun number(value: C): NumberedPolynomial<C> =
|
||||||
if (value == 0) zero
|
NumberedPolynomial(mapOf(emptyList<UInt>() to value))
|
||||||
else NumberedPolynomial(mapOf(emptyList<UInt>() to value))
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns negation of the polynomial.
|
* 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> =
|
override operator fun NumberedPolynomial<C>.plus(other: NumberedPolynomial<C>): 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) { it.value }
|
||||||
other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value }
|
other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value }
|
||||||
}
|
}
|
||||||
@ -441,7 +420,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
*/
|
*/
|
||||||
override operator fun NumberedPolynomial<C>.minus(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
override operator fun NumberedPolynomial<C>.minus(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
||||||
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) { it.value }
|
||||||
other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value }
|
other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value }
|
||||||
}
|
}
|
||||||
@ -450,12 +429,8 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
* Returns product of the polynomials.
|
* Returns product of the polynomials.
|
||||||
*/
|
*/
|
||||||
override operator fun NumberedPolynomial<C>.times(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
override operator fun NumberedPolynomial<C>.times(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
||||||
when {
|
|
||||||
isZero() -> zero
|
|
||||||
other.isZero() -> zero
|
|
||||||
else ->
|
|
||||||
NumberedPolynomial<C>(
|
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) {
|
for ((degs1, c1) in coefficients) for ((degs2, c2) in other.coefficients) {
|
||||||
val degs =
|
val degs =
|
||||||
(0..max(degs1.lastIndex, degs2.lastIndex))
|
(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).
|
* 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,
|
* Maximal index (ID) of variable occurring in the polynomial with positive power. If there is no such variable,
|
||||||
* the result is `-1`.
|
* the result is `-1`.
|
||||||
*/
|
*/
|
||||||
public val NumberedPolynomial<C>.lastVariable: Int
|
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
|
* Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is
|
||||||
* zero, degree is -1.
|
* zero, degree is -1.
|
||||||
*/
|
*/
|
||||||
override val NumberedPolynomial<C>.degree: Int
|
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
|
* 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.
|
* 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>
|
public val NumberedPolynomial<C>.degrees: List<UInt>
|
||||||
get() =
|
get() =
|
||||||
MutableList(lastVariable + 1) { 0u }.apply {
|
MutableList(lastVariable + 1) { 0u }.apply {
|
||||||
coefficients.entries.forEach { (degs, c) ->
|
coefficients.entries.forEach { (degs, _) ->
|
||||||
if (c.isNotZero()) degs.forEachIndexed { index, deg ->
|
degs.forEachIndexed { index, deg ->
|
||||||
this[index] = max(this[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].
|
* Counts degree of the polynomial by the specified [variable].
|
||||||
*/
|
*/
|
||||||
public fun NumberedPolynomial<C>.degreeBy(variable: Int): UInt =
|
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].
|
* Counts degree of the polynomial by the specified [variables].
|
||||||
*/
|
*/
|
||||||
public fun NumberedPolynomial<C>.degreeBy(variables: Collection<Int>): UInt =
|
public fun NumberedPolynomial<C>.degreeBy(variables: Collection<Int>): UInt =
|
||||||
coefficients.entries.maxOfOrNull { (degs, c) ->
|
coefficients.entries.maxOfOrNull { (degs, _) ->
|
||||||
if (c.isZero()) 0u else degs.withIndex().filter { (index, _) -> index in variables }.sumOf { it.value }
|
degs.withIndex().filter { (index, _) -> index in variables }.sumOf { it.value }
|
||||||
} ?: 0u
|
} ?: 0u
|
||||||
/**
|
/**
|
||||||
* Count of variables occurring in the polynomial with positive power. If there is no such variable,
|
* 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
|
public val NumberedPolynomial<C>.countOfVariables: Int
|
||||||
get() =
|
get() =
|
||||||
MutableList(lastVariable + 1) { false }.apply {
|
MutableList(lastVariable + 1) { false }.apply {
|
||||||
coefficients.entries.forEach { (degs, c) ->
|
coefficients.entries.forEach { (degs, _) ->
|
||||||
if (c.isNotZero()) degs.forEachIndexed { index, deg ->
|
degs.forEachIndexed { index, deg ->
|
||||||
if (deg != 0u) this[index] = true
|
if (deg != 0u) this[index] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.count { it }
|
}.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")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
public inline fun NumberedPolynomial<C>.substitute(argument: Map<Int, C>): NumberedPolynomial<C> = this.substitute(ring, argument)
|
public inline fun NumberedPolynomial<C>.substitute(argument: Map<Int, C>): NumberedPolynomial<C> = this.substitute(ring, argument)
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
@ -629,35 +528,6 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
@JvmName("invokePolynomial")
|
@JvmName("invokePolynomial")
|
||||||
public inline operator fun NumberedPolynomial<C>.invoke(argument: Map<Int, NumberedPolynomial<C>>): NumberedPolynomial<C> = this.substitute(ring, argument)
|
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
|
// TODO: Move to other constructors with context receiver
|
||||||
public fun C.asNumberedPolynomial() : NumberedPolynomial<C> = NumberedPolynomial<C>(mapOf(emptyList<UInt>() to this))
|
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
|
// 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")
|
@Suppress("FunctionName")
|
||||||
public fun <C, A: Ring<C>> NumberedRationalFunctionSpace<C, A>.NumberedRationalFunction(numeratorCoefficients: Map<List<UInt>, C>, denominatorCoefficients: Map<List<UInt>, C>): NumberedRationalFunction<C> =
|
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")
|
NumberedRationalFunction<C>(
|
||||||
else NumberedRationalFunction<C>(
|
NumberedPolynomial(numeratorCoefficients, toCheckInput = true),
|
||||||
NumberedPolynomial(numeratorCoefficients),
|
NumberedPolynomial(denominatorCoefficients, toCheckInput = true)
|
||||||
NumberedPolynomial(denominatorCoefficients)
|
|
||||||
)
|
)
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
public fun <C, A: Ring<C>> A.NumberedRationalFunction(numeratorCoefficients: Map<List<UInt>, C>, denominatorCoefficients: Map<List<UInt>, C>): NumberedRationalFunction<C> =
|
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")
|
NumberedRationalFunction<C>(
|
||||||
else NumberedRationalFunction<C>(
|
NumberedPolynomial(numeratorCoefficients, toCheckInput = true),
|
||||||
NumberedPolynomial(numeratorCoefficients),
|
NumberedPolynomial(denominatorCoefficients, toCheckInput = true)
|
||||||
NumberedPolynomial(denominatorCoefficients)
|
|
||||||
)
|
)
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
public fun <C, A: Ring<C>> NumberedRationalFunctionSpace<C, A>.NumberedRationalFunction(numerator: NumberedPolynomial<C>): NumberedRationalFunction<C> =
|
public fun <C, A: Ring<C>> NumberedRationalFunctionSpace<C, A>.NumberedRationalFunction(numerator: NumberedPolynomial<C>): NumberedRationalFunction<C> =
|
||||||
NumberedRationalFunction<C>(numerator, polynomialOne)
|
NumberedRationalFunction<C>(numerator, polynomialOne)
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
public fun <C, A: Ring<C>> A.NumberedRationalFunction(numerator: NumberedPolynomial<C>): NumberedRationalFunction<C> =
|
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")
|
@Suppress("FunctionName")
|
||||||
public fun <C, A: Ring<C>> NumberedRationalFunctionSpace<C, A>.NumberedRationalFunction(numeratorCoefficients: Map<List<UInt>, C>): NumberedRationalFunction<C> =
|
public fun <C, A: Ring<C>> NumberedRationalFunctionSpace<C, A>.NumberedRationalFunction(numeratorCoefficients: Map<List<UInt>, C>): NumberedRationalFunction<C> =
|
||||||
NumberedRationalFunction<C>(
|
NumberedRationalFunction<C>(
|
||||||
NumberedPolynomial(numeratorCoefficients),
|
NumberedPolynomial(numeratorCoefficients, toCheckInput = true),
|
||||||
polynomialOne
|
polynomialOne
|
||||||
)
|
)
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
public fun <C, A: Ring<C>> A.NumberedRationalFunction(numeratorCoefficients: Map<List<UInt>, C>): NumberedRationalFunction<C> =
|
public fun <C, A: Ring<C>> A.NumberedRationalFunction(numeratorCoefficients: Map<List<UInt>, C>): NumberedRationalFunction<C> =
|
||||||
NumberedRationalFunction<C>(
|
NumberedRationalFunction<C>(
|
||||||
NumberedPolynomial(numeratorCoefficients),
|
NumberedPolynomial(numeratorCoefficients, toCheckInput = true),
|
||||||
NumberedPolynomial(mapOf(emptyList<UInt>() to one))
|
NumberedPolynomial(mapOf(emptyList<UInt>() to one), toCheckInput = false)
|
||||||
)
|
)
|
||||||
|
|
||||||
public class NumberedRationalFunctionSpace<C, A: Ring<C>> (
|
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)
|
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,
|
* Maximal index (ID) of variable occurring in the polynomial with positive power. If there is no such variable,
|
||||||
* the result is `-1`.
|
* the result is `-1`.
|
||||||
@ -152,13 +120,13 @@ public class NumberedRationalFunctionSpace<C, A: Ring<C>> (
|
|||||||
public val NumberedRationalFunction<C>.countOfVariables: Int
|
public val NumberedRationalFunction<C>.countOfVariables: Int
|
||||||
get() =
|
get() =
|
||||||
MutableList(lastVariable + 1) { false }.apply {
|
MutableList(lastVariable + 1) { false }.apply {
|
||||||
numerator.coefficients.entries.forEach { (degs, c) ->
|
numerator.coefficients.entries.forEach { (degs, _) ->
|
||||||
if (c.isNotZero()) degs.forEachIndexed { index, deg ->
|
degs.forEachIndexed { index, deg ->
|
||||||
if (deg != 0u) this[index] = true
|
if (deg != 0u) this[index] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
denominator.coefficients.entries.forEach { (degs, c) ->
|
denominator.coefficients.entries.forEach { (degs, _) ->
|
||||||
if (c.isNotZero()) degs.forEachIndexed { index, deg ->
|
degs.forEachIndexed { index, deg ->
|
||||||
if (deg != 0u) this[index] = true
|
if (deg != 0u) this[index] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,31 +155,6 @@ public interface PolynomialSpace<C, P: Polynomial<C>> : Ring<P> {
|
|||||||
@JsName("constantPower")
|
@JsName("constantPower")
|
||||||
public fun power(arg: C, exponent: UInt) : C
|
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).
|
* 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)
|
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).
|
* 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
|
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
|
* Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is
|
||||||
* zero, degree is -1.
|
* zero, degree is -1.
|
||||||
*/
|
*/
|
||||||
public val P.degree: Int
|
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 add(left: P, right: P): P = left + right
|
||||||
override fun multiply(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")
|
@JsName("constantPower")
|
||||||
public fun power(arg: C, exponent: UInt) : C
|
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).
|
* 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
|
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).
|
* 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
|
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.
|
* 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)
|
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).
|
* 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
|
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
|
* Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is
|
||||||
* zero, degree is -1.
|
* zero, degree is -1.
|
||||||
*/
|
*/
|
||||||
public val P.degree: Int
|
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
|
* Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is
|
||||||
* zero, degree is -1.
|
* zero, degree is -1.
|
||||||
@ -813,31 +687,6 @@ public interface RationalFunctionalSpaceOverPolynomialSpace<
|
|||||||
@JvmName("constantPower")
|
@JvmName("constantPower")
|
||||||
public override fun power(arg: C, exponent: UInt) : C = polynomialRing { power(arg, exponent) }
|
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).
|
* 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) }
|
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).
|
* Instance of zero polynomial (zero of the polynomial ring).
|
||||||
*/
|
*/
|
||||||
@ -941,47 +765,11 @@ public interface RationalFunctionalSpaceOverPolynomialSpace<
|
|||||||
*/
|
*/
|
||||||
public override val polynomialOne: P get() = polynomialRing.one
|
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
|
* Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is
|
||||||
* zero, degree is -1.
|
* zero, degree is -1.
|
||||||
*/
|
*/
|
||||||
public override val P.degree: Int get() = polynomialRing { this@degree.degree }
|
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
|
denominator
|
||||||
)
|
)
|
||||||
|
|
||||||
public override operator fun R.div(other: Int): R {
|
public override operator fun R.div(other: Int): R =
|
||||||
val otherAsConstant = constantNumber(other)
|
constructRationalFunction(
|
||||||
require(otherAsConstant.isNotZero()) { "/ by zero." }
|
|
||||||
return constructRationalFunction(
|
|
||||||
numerator,
|
numerator,
|
||||||
(denominator * other).also {
|
denominator * other
|
||||||
check(it.isNotZero()) {
|
|
||||||
"Got zero denominator during division of rational functions to constant. It means underlying ring of polynomials is not integral domain."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns sum of the integer represented as rational function and the rational function.
|
* Returns sum of the integer represented as rational function and the rational function.
|
||||||
@ -1076,13 +857,11 @@ public abstract class PolynomialSpaceOfFractions<
|
|||||||
other.denominator
|
other.denominator
|
||||||
)
|
)
|
||||||
|
|
||||||
public override operator fun Int.div(other: R): R {
|
public override operator fun Int.div(other: R): R =
|
||||||
require(other.numerator.isNotZero()) { "/ by zero." }
|
constructRationalFunction(
|
||||||
return constructRationalFunction(
|
|
||||||
this * other.denominator,
|
this * other.denominator,
|
||||||
other.numerator
|
other.numerator
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the integer [value] to rational function.
|
* Converts the integer [value] to rational function.
|
||||||
@ -1119,13 +898,11 @@ public abstract class PolynomialSpaceOfFractions<
|
|||||||
other.denominator
|
other.denominator
|
||||||
)
|
)
|
||||||
|
|
||||||
public override operator fun C.div(other: R): R {
|
public override operator fun C.div(other: R): R =
|
||||||
require(other.numerator.isNotZero()) { "/ by zero." }
|
constructRationalFunction(
|
||||||
return constructRationalFunction(
|
|
||||||
this * other.denominator,
|
this * other.denominator,
|
||||||
other.numerator
|
other.numerator
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns sum of the constant represented as rational function and the rational function.
|
* Returns sum of the constant represented as rational function and the rational function.
|
||||||
@ -1152,17 +929,11 @@ public abstract class PolynomialSpaceOfFractions<
|
|||||||
denominator
|
denominator
|
||||||
)
|
)
|
||||||
|
|
||||||
public override operator fun R.div(other: C): R {
|
public override operator fun R.div(other: C): R =
|
||||||
require(other.isNotZero()) { "/ by zero." }
|
constructRationalFunction(
|
||||||
return constructRationalFunction(
|
|
||||||
numerator,
|
numerator,
|
||||||
(denominator * other).also {
|
denominator * other
|
||||||
check(it.isNotZero()) {
|
|
||||||
"Got zero denominator during division of rational functions to constant. It means underlying ring of polynomials is not integral domain."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the constant [value] to rational function.
|
* Converts the constant [value] to rational function.
|
||||||
@ -1194,13 +965,11 @@ public abstract class PolynomialSpaceOfFractions<
|
|||||||
other.denominator
|
other.denominator
|
||||||
)
|
)
|
||||||
|
|
||||||
public override operator fun P.div(other: R): R {
|
public override operator fun P.div(other: R): R =
|
||||||
require(other.numerator.isNotZero()) { "/ by zero." }
|
constructRationalFunction(
|
||||||
return constructRationalFunction(
|
|
||||||
this * other.denominator,
|
this * other.denominator,
|
||||||
other.numerator
|
other.numerator
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns sum of the polynomial represented as rational function and the rational function.
|
* Returns sum of the polynomial represented as rational function and the rational function.
|
||||||
@ -1227,17 +996,11 @@ public abstract class PolynomialSpaceOfFractions<
|
|||||||
denominator
|
denominator
|
||||||
)
|
)
|
||||||
|
|
||||||
public override operator fun R.div(other: P): R {
|
public override operator fun R.div(other: P): R =
|
||||||
require(other.isNotZero()) { "/ by zero." }
|
constructRationalFunction(
|
||||||
return constructRationalFunction(
|
|
||||||
numerator,
|
numerator,
|
||||||
(denominator * other).also {
|
denominator * other
|
||||||
require(it.isNotZero()) {
|
|
||||||
"Got zero denominator during division of rational functions to polynomial. It means underlying ring of polynomials is not integral domain."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the polynomial [value] to rational function.
|
* Converts the polynomial [value] to rational function.
|
||||||
@ -1254,11 +1017,7 @@ public abstract class PolynomialSpaceOfFractions<
|
|||||||
public override operator fun R.plus(other: R): R =
|
public override operator fun R.plus(other: R): R =
|
||||||
constructRationalFunction(
|
constructRationalFunction(
|
||||||
numerator * other.denominator + denominator * other.numerator,
|
numerator * other.denominator + denominator * other.numerator,
|
||||||
(denominator * other.denominator).also {
|
denominator * other.denominator
|
||||||
check(it.isNotZero()) {
|
|
||||||
"Got zero denominator during addition of rational functions. It means underlying ring of polynomials is not integral domain."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
* Returns difference of the rational functions.
|
* Returns difference of the rational functions.
|
||||||
@ -1266,11 +1025,7 @@ public abstract class PolynomialSpaceOfFractions<
|
|||||||
public override operator fun R.minus(other: R): R =
|
public override operator fun R.minus(other: R): R =
|
||||||
constructRationalFunction(
|
constructRationalFunction(
|
||||||
numerator * other.denominator - denominator * other.numerator,
|
numerator * other.denominator - denominator * other.numerator,
|
||||||
(denominator * other.denominator).also {
|
denominator * other.denominator
|
||||||
check(it.isNotZero()) {
|
|
||||||
"Got zero denominator during subtraction of rational functions. It means underlying ring of polynomials is not integral domain."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
* Returns product of the rational functions.
|
* Returns product of the rational functions.
|
||||||
@ -1278,24 +1033,14 @@ public abstract class PolynomialSpaceOfFractions<
|
|||||||
public override operator fun R.times(other: R): R =
|
public override operator fun R.times(other: R): R =
|
||||||
constructRationalFunction(
|
constructRationalFunction(
|
||||||
numerator * other.numerator,
|
numerator * other.numerator,
|
||||||
(denominator * other.denominator).also {
|
denominator * other.denominator
|
||||||
check(it.isNotZero()) {
|
|
||||||
"Got zero denominator during multiplication of rational functions. It means underlying ring of polynomials is not integral domain."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
public override operator fun R.div(other: R): R {
|
public override operator fun R.div(other: R): R =
|
||||||
require(other.isNotZero()) { "/ by zero." }
|
constructRationalFunction(
|
||||||
return constructRationalFunction(
|
|
||||||
numerator * other.denominator,
|
numerator * other.denominator,
|
||||||
(denominator * other.numerator).also {
|
denominator * other.numerator
|
||||||
check(it.isNotZero()) {
|
|
||||||
"Got zero denominator during division of rational functions. It means underlying ring of polynomials is not integral domain."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instance of zero rational function (zero of the rational functions ring).
|
* 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 {
|
public fun <C> ListPolynomial<C>.substitute(ring: Ring<C>, arg: ListPolynomial<C>) : ListPolynomial<C> = ring {
|
||||||
if (coefficients.isEmpty()) return ListPolynomial(emptyList())
|
if (coefficients.isEmpty()) return ListPolynomial(emptyList())
|
||||||
|
|
||||||
val thisDegree = coefficients.indexOfLast { it != zero }
|
val thisDegree = coefficients.lastIndex
|
||||||
if (thisDegree == -1) return ListPolynomial(emptyList())
|
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()
|
if (argDegree == -1) return coefficients[0].asListPolynomial()
|
||||||
val constantZero = zero
|
val constantZero = zero
|
||||||
val resultCoefs: MutableList<C> = MutableList(thisDegree * argDegree + 1) { constantZero }
|
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
|
resultDegree += argDegree
|
||||||
}
|
}
|
||||||
|
|
||||||
with(resultCoefs) { while (isNotEmpty() && elementAt(lastIndex) == constantZero) removeAt(lastIndex) }
|
|
||||||
return ListPolynomial<C>(resultCoefs)
|
return ListPolynomial<C>(resultCoefs)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,7 +167,6 @@ public fun <C, A> ListPolynomial<C>.derivative(
|
|||||||
ListPolynomial(
|
ListPolynomial(
|
||||||
buildList(max(0, coefficients.size - 1)) {
|
buildList(max(0, coefficients.size - 1)) {
|
||||||
for (deg in 1 .. coefficients.lastIndex) add(number(deg) * coefficients[deg])
|
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)) {
|
buildList(max(0, coefficients.size - order)) {
|
||||||
for (deg in order.. coefficients.lastIndex)
|
for (deg in order.. coefficients.lastIndex)
|
||||||
add((deg - order + 1 .. deg).fold(coefficients[deg]) { acc, d -> acc * number(d) })
|
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) {
|
buildList(coefficients.size + 1) {
|
||||||
add(zero)
|
add(zero)
|
||||||
coefficients.mapIndexedTo(this) { index, t -> t / number(index + 1) }
|
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) {
|
buildList(coefficients.size + order) {
|
||||||
repeat(order) { add(zero) }
|
repeat(order) { add(zero) }
|
||||||
coefficients.mapIndexedTo(this) { index, c -> (1..order).fold(c) { acc, i -> acc / number(index + i) } }
|
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 {
|
internal fun <C> ListPolynomial<C>.substituteRationalFunctionTakeNumerator(ring: Ring<C>, arg: ListRationalFunction<C>): ListPolynomial<C> = ring {
|
||||||
if (coefficients.isEmpty()) return ListPolynomial(emptyList())
|
if (coefficients.isEmpty()) return ListPolynomial(emptyList())
|
||||||
|
|
||||||
val thisDegree = coefficients.indexOfLast { it != zero }
|
val thisDegree = coefficients.lastIndex
|
||||||
if (thisDegree == -1) return ListPolynomial(emptyList())
|
if (thisDegree == -1) return ListPolynomial(emptyList())
|
||||||
val thisDegreeLog2 = 31 - thisDegree.countLeadingZeroBits()
|
val thisDegreeLog2 = 31 - thisDegree.countLeadingZeroBits()
|
||||||
val numeratorDegree = arg.numerator.coefficients.indexOfLast { it != zero }
|
val numeratorDegree = arg.numerator.coefficients.lastIndex
|
||||||
val denominatorDegree = arg.denominator.coefficients.indexOfLast { it != zero }
|
val denominatorDegree = arg.denominator.coefficients.lastIndex
|
||||||
val argDegree = max(numeratorDegree, denominatorDegree)
|
val argDegree = max(numeratorDegree, denominatorDegree)
|
||||||
val constantZero = zero
|
val constantZero = zero
|
||||||
val powersOf2 = buildList<Int>(thisDegreeLog2 + 1) {
|
val powersOf2 = buildList<Int>(thisDegreeLog2 + 1) {
|
||||||
|
@ -9,7 +9,7 @@ import space.kscience.kmath.test.misc.*
|
|||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
|
|
||||||
class ListPolynomialTest {
|
class ListPolynomialTest { // TODO: Adapt tests to changes
|
||||||
@Test
|
@Test
|
||||||
fun test_Polynomial_Int_plus() {
|
fun test_Polynomial_Int_plus() {
|
||||||
RationalField.listPolynomial {
|
RationalField.listPolynomial {
|
||||||
@ -489,94 +489,6 @@ class ListPolynomialTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Test
|
@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() {
|
fun test_Polynomial_degree() {
|
||||||
RationalField.listPolynomial {
|
RationalField.listPolynomial {
|
||||||
assertEquals(
|
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
|
import kotlin.test.assertFailsWith
|
||||||
|
|
||||||
|
|
||||||
class ListPolynomialUtilTest {
|
class ListPolynomialUtilTest { // TODO: Adapt tests to changes
|
||||||
@Test
|
@Test
|
||||||
fun test_substitute_Double() {
|
fun test_substitute_Double() {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
|
Loading…
Reference in New Issue
Block a user