diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt index 3d1b91f7b..908e89534 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -58,6 +58,8 @@ internal fun Map.cleanUp() = filterValues { it > 0U } @Suppress("FunctionName", "NOTHING_TO_INLINE") internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(coefs, toCheckInput) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(coefs, toCheckInput) @Suppress("FunctionName") internal fun > A.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial { if (!toCheckInput) return LabeledPolynomial(coefs) @@ -70,13 +72,13 @@ internal fun > A.LabeledPolynomial(coefs: Map, C fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value } - return LabeledPolynomial( - fixedCoefs.filterValues { it != zero } - ) + return LabeledPolynomial(fixedCoefs) } @Suppress("FunctionName", "NOTHING_TO_INLINE") internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs, toCheckInput) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs, toCheckInput) @Suppress("FunctionName") internal fun > A.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial { if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) @@ -89,13 +91,13 @@ internal fun > A.LabeledPolynomial(pairs: Collection( - fixedCoefs.filterValues { it != zero } - ) + return LabeledPolynomial(fixedCoefs) } @Suppress("FunctionName", "NOTHING_TO_INLINE") internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs = pairs, toCheckInput = toCheckInput) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs = pairs, toCheckInput = toCheckInput) @Suppress("FunctionName") internal fun > A.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial { if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) @@ -108,25 +110,29 @@ internal fun > A.LabeledPolynomial(vararg pairs: Pair( - fixedCoefs.filterValues { it != zero } - ) + return LabeledPolynomial(fixedCoefs) } @Suppress("FunctionName") public fun > A.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) @Suppress("FunctionName") public fun > LabeledPolynomialSpace.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) +@Suppress("FunctionName") +public fun > LabeledRationalFunctionSpace.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) @Suppress("FunctionName") public fun > A.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) @Suppress("FunctionName") public fun > LabeledPolynomialSpace.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > LabeledRationalFunctionSpace.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) @Suppress("FunctionName") public fun > A.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) @Suppress("FunctionName") public fun > LabeledPolynomialSpace.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > LabeledRationalFunctionSpace.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) //context(A) //public fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to one)) @@ -196,19 +202,17 @@ public class LabeledPolynomialSpace>( */ public override operator fun LabeledPolynomial.plus(other: Int): LabeledPolynomial = if (other == 0) this - else - LabeledPolynomial( - coefficients - .toMutableMap() + else with(coefficients) { + if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to other.asConstant())) + else LabeledPolynomial( + toMutableMap() .apply { val degs = emptyMap() - val result = getOrElse(degs) { constantZero } + other - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = getOrElse(degs) { constantZero } + other } ) + } /** * Returns difference between the polynomial and the integer represented as polynomial. * @@ -216,19 +220,17 @@ public class LabeledPolynomialSpace>( */ public override operator fun LabeledPolynomial.minus(other: Int): LabeledPolynomial = if (other == 0) this - else - LabeledPolynomial( - coefficients - .toMutableMap() + else with(coefficients) { + if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to (-other).asConstant())) + else LabeledPolynomial( + toMutableMap() .apply { val degs = emptyMap() - val result = getOrElse(degs) { constantZero } - other - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = getOrElse(degs) { constantZero } - other } ) + } /** * Returns product of the polynomial and the integer represented as polynomial. * @@ -238,7 +240,8 @@ public class LabeledPolynomialSpace>( if (other == 0) zero else LabeledPolynomial( coefficients - .applyAndRemoveZeros { + .toMutableMap() + .apply { for (degs in keys) this[degs] = this[degs]!! * other } ) @@ -250,19 +253,17 @@ public class LabeledPolynomialSpace>( */ public override operator fun Int.plus(other: LabeledPolynomial): LabeledPolynomial = if (this == 0) other - else - LabeledPolynomial( - other.coefficients - .toMutableMap() + else with(other.coefficients) { + if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@plus.asConstant())) + else LabeledPolynomial( + toMutableMap() .apply { val degs = emptyMap() - val result = this@plus + getOrElse(degs) { constantZero } - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = this@plus + getOrElse(degs) { constantZero } } ) + } /** * Returns difference between the integer represented as polynomial and the polynomial. * @@ -270,19 +271,17 @@ public class LabeledPolynomialSpace>( */ public override operator fun Int.minus(other: LabeledPolynomial): LabeledPolynomial = if (this == 0) other - else - LabeledPolynomial( - other.coefficients - .toMutableMap() + else with(other.coefficients) { + if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@minus.asConstant())) + else LabeledPolynomial( + toMutableMap() .apply { val degs = emptyMap() - val result = this@minus - getOrElse(degs) { constantZero } - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = this@minus - getOrElse(degs) { constantZero } } ) + } /** * Returns product of the integer represented as polynomial and the polynomial. * @@ -292,7 +291,8 @@ public class LabeledPolynomialSpace>( if (this == 0) zero else LabeledPolynomial( other.coefficients - .applyAndRemoveZeros { + .toMutableMap() + .apply { for (degs in keys) this[degs] = this@times * this[degs]!! } ) @@ -303,46 +303,32 @@ public class LabeledPolynomialSpace>( public override fun number(value: Int): LabeledPolynomial = number(constantNumber(value)) public override operator fun C.plus(other: Symbol): LabeledPolynomial = - if (isZero()) LabeledPolynomial(mapOf( - mapOf(other to 1U) to constantOne, - )) - else LabeledPolynomial(mapOf( + LabeledPolynomial(mapOf( mapOf(other to 1U) to constantOne, emptyMap() to this@plus, )) public override operator fun C.minus(other: Symbol): LabeledPolynomial = - if (isZero()) LabeledPolynomial(mapOf( - mapOf(other to 1U) to -constantOne, - )) - else LabeledPolynomial(mapOf( + LabeledPolynomial(mapOf( mapOf(other to 1U) to -constantOne, emptyMap() to this@minus, )) public override operator fun C.times(other: Symbol): LabeledPolynomial = - if (isZero()) zero - else LabeledPolynomial(mapOf( + LabeledPolynomial(mapOf( mapOf(other to 1U) to this@times, )) public override operator fun Symbol.plus(other: C): LabeledPolynomial = - if (other.isZero()) LabeledPolynomial(mapOf( - mapOf(this@plus to 1U) to constantOne, - )) - else LabeledPolynomial(mapOf( + LabeledPolynomial(mapOf( mapOf(this@plus to 1U) to constantOne, emptyMap() to other, )) public override operator fun Symbol.minus(other: C): LabeledPolynomial = - if (other.isZero()) LabeledPolynomial(mapOf( - mapOf(this@minus to 1U) to -constantOne, - )) - else LabeledPolynomial(mapOf( + LabeledPolynomial(mapOf( mapOf(this@minus to 1U) to -constantOne, emptyMap() to other, )) public override operator fun Symbol.times(other: C): LabeledPolynomial = - if (other.isZero()) zero - else LabeledPolynomial(mapOf( + LabeledPolynomial(mapOf( mapOf(this@times to 1U) to other, )) @@ -350,18 +336,14 @@ public class LabeledPolynomialSpace>( * Returns sum of the constant represented as polynomial and the polynomial. */ override operator fun C.plus(other: LabeledPolynomial): LabeledPolynomial = - if (this.isZero()) other - else with(other.coefficients) { + with(other.coefficients) { if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@plus)) else LabeledPolynomial( toMutableMap() .apply { val degs = emptyMap() - val result = this@plus + getOrElse(degs) { constantZero } - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = this@plus + getOrElse(degs) { constantZero } } ) } @@ -369,8 +351,7 @@ public class LabeledPolynomialSpace>( * Returns difference between the constant represented as polynomial and the polynomial. */ override operator fun C.minus(other: LabeledPolynomial): LabeledPolynomial = - if (this.isZero()) other - else with(other.coefficients) { + with(other.coefficients) { if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to this@minus)) else LabeledPolynomial( toMutableMap() @@ -379,10 +360,7 @@ public class LabeledPolynomialSpace>( val degs = emptyMap() - val result = this@minus - getOrElse(degs) { constantZero } - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = this@minus - getOrElse(degs) { constantZero } } ) } @@ -390,10 +368,10 @@ public class LabeledPolynomialSpace>( * Returns product of the constant represented as polynomial and the polynomial. */ override operator fun C.times(other: LabeledPolynomial): LabeledPolynomial = - if (this.isZero()) zero - else LabeledPolynomial( + LabeledPolynomial( other.coefficients - .applyAndRemoveZeros { + .toMutableMap() + .apply { for (degs in keys) this[degs] = this@times * this[degs]!! } ) @@ -402,18 +380,14 @@ public class LabeledPolynomialSpace>( * Returns sum of the constant represented as polynomial and the polynomial. */ override operator fun LabeledPolynomial.plus(other: C): LabeledPolynomial = - if (other.isZero()) this - else with(coefficients) { + with(coefficients) { if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to other)) else LabeledPolynomial( toMutableMap() .apply { val degs = emptyMap() - val result = getOrElse(degs) { constantZero } + other - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = getOrElse(degs) { constantZero } + other } ) } @@ -421,8 +395,7 @@ public class LabeledPolynomialSpace>( * Returns difference between the constant represented as polynomial and the polynomial. */ override operator fun LabeledPolynomial.minus(other: C): LabeledPolynomial = - if (other.isZero()) this - else with(coefficients) { + with(coefficients) { if (isEmpty()) LabeledPolynomial(mapOf(emptyMap() to other)) else LabeledPolynomial( toMutableMap() @@ -431,10 +404,7 @@ public class LabeledPolynomialSpace>( val degs = emptyMap() - val result = getOrElse(degs) { constantZero } - other - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = getOrElse(degs) { constantZero } - other } ) } @@ -442,10 +412,10 @@ public class LabeledPolynomialSpace>( * Returns product of the constant represented as polynomial and the polynomial. */ override operator fun LabeledPolynomial.times(other: C): LabeledPolynomial = - if (other.isZero()) zero - else LabeledPolynomial( + LabeledPolynomial( coefficients - .applyAndRemoveZeros { + .toMutableMap() + .apply { for (degs in keys) this[degs] = this[degs]!! * other } ) @@ -454,8 +424,7 @@ public class LabeledPolynomialSpace>( * Converts the constant [value] to polynomial. */ public override fun number(value: C): LabeledPolynomial = - if (value == 0) zero - else LabeledPolynomial(mapOf(emptyMap() to value)) + LabeledPolynomial(mapOf(emptyMap() to value)) public override operator fun Symbol.unaryPlus(): LabeledPolynomial = LabeledPolynomial(mapOf( @@ -495,10 +464,7 @@ public class LabeledPolynomialSpace>( .apply { val degs = mapOf(this@plus to 1U) - val result = constantOne + getOrElse(degs) { constantZero } - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = constantOne + getOrElse(degs) { constantZero } } ) } @@ -512,10 +478,7 @@ public class LabeledPolynomialSpace>( val degs = mapOf(this@minus to 1U) - val result = constantOne - getOrElse(degs) { constantZero } - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = constantOne - getOrElse(degs) { constantZero } } ) } @@ -533,10 +496,7 @@ public class LabeledPolynomialSpace>( .apply { val degs = mapOf(other to 1U) - val result = constantOne + getOrElse(degs) { constantZero } - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = constantOne + getOrElse(degs) { constantZero } } ) } @@ -548,10 +508,7 @@ public class LabeledPolynomialSpace>( .apply { val degs = mapOf(other to 1U) - val result = constantOne - getOrElse(degs) { constantZero } - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = constantOne - getOrElse(degs) { constantZero } } ) } @@ -573,7 +530,7 @@ public class LabeledPolynomialSpace>( */ override operator fun LabeledPolynomial.plus(other: LabeledPolynomial): LabeledPolynomial = LabeledPolynomial( - buildCoefficients(coefficients.size + other.coefficients.size) { + buildMap(coefficients.size + other.coefficients.size) { other.coefficients.mapValuesTo(this) { it.value } other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value } } @@ -583,7 +540,7 @@ public class LabeledPolynomialSpace>( */ override operator fun LabeledPolynomial.minus(other: LabeledPolynomial): LabeledPolynomial = LabeledPolynomial( - buildCoefficients(coefficients.size + other.coefficients.size) { + buildMap(coefficients.size + other.coefficients.size) { other.coefficients.mapValuesTo(this) { it.value } other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value } } @@ -592,20 +549,16 @@ public class LabeledPolynomialSpace>( * Returns product of the polynomials. */ override operator fun LabeledPolynomial.times(other: LabeledPolynomial): LabeledPolynomial = - when { - isZero() -> zero - other.isZero() -> zero - else -> LabeledPolynomial( - buildCoefficients(coefficients.size * other.coefficients.size) { - for ((degs1, c1) in coefficients) for ((degs2, c2) in other.coefficients) { - val degs = degs1.toMutableMap() - degs2.mapValuesTo(degs) { (variable, deg) -> degs.getOrElse(variable) { 0u } + deg } - val c = c1 * c2 - this[degs] = if (degs in this) this[degs]!! + c else c - } + LabeledPolynomial( + buildMap(coefficients.size * other.coefficients.size) { + for ((degs1, c1) in coefficients) for ((degs2, c2) in other.coefficients) { + val degs = degs1.toMutableMap() + degs2.mapValuesTo(degs) { (variable, deg) -> degs.getOrElse(variable) { 0u } + deg } + val c = c1 * c2 + this[degs] = if (degs in this) this[degs]!! + c else c } - ) - } + } + ) /** * Instance of zero polynomial (zero of the polynomial ring). @@ -616,22 +569,12 @@ public class LabeledPolynomialSpace>( */ override val one: LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to constantOne)) - /** - * Checks equality of the polynomials. - */ - override infix fun LabeledPolynomial.equalsTo(other: LabeledPolynomial): Boolean = - when { - this === other -> true - else -> coefficients.size == other.coefficients.size && - coefficients.all { (key, value) -> with(other.coefficients) { key in this && this[key] == value } } - } - /** * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is * zero, degree is -1. */ override val LabeledPolynomial.degree: Int - get() = coefficients.entries.maxOfOrNull { (degs, c) -> if (c.isZero()) -1 else degs.values.sum().toInt() } ?: -1 + get() = coefficients.entries.maxOfOrNull { (degs, c) -> degs.values.sum().toInt() } ?: -1 /** * Map that associates variables (that appear in the polynomial in positive exponents) with their most exponents * in which they are appeared in the polynomial. @@ -642,8 +585,8 @@ public class LabeledPolynomialSpace>( public override val LabeledPolynomial.degrees: Map get() = buildMap { - coefficients.entries.forEach { (degs, c) -> - if (c.isNotZero()) degs.mapValuesTo(this) { (variable, deg) -> + coefficients.entries.forEach { (degs, _) -> + degs.mapValuesTo(this) { (variable, deg) -> max(getOrElse(variable) { 0u }, deg) } } @@ -652,55 +595,25 @@ public class LabeledPolynomialSpace>( * Counts degree of the polynomial by the specified [variable]. */ public override fun LabeledPolynomial.degreeBy(variable: Symbol): UInt = - coefficients.entries.maxOfOrNull { (degs, c) -> if (c.isZero()) 0u else degs.getOrElse(variable) { 0u } } ?: 0u + coefficients.entries.maxOfOrNull { (degs, _) -> degs.getOrElse(variable) { 0u } } ?: 0u /** * Counts degree of the polynomial by the specified [variables]. */ public override fun LabeledPolynomial.degreeBy(variables: Collection): UInt = - coefficients.entries.maxOfOrNull { (degs, c) -> if (c.isZero()) 0u else degs.filterKeys { it in variables }.values.sum() } ?: 0u + coefficients.entries.maxOfOrNull { (degs, _) -> degs.filterKeys { it in variables }.values.sum() } ?: 0u /** * Set of all variables that appear in the polynomial in positive exponents. */ public override val LabeledPolynomial.variables: Set get() = buildSet { - coefficients.entries.forEach { (degs, c) -> if (c.isNotZero()) addAll(degs.keys) } + coefficients.entries.forEach { (degs, _) -> addAll(degs.keys) } } /** * Count of all variables that appear in the polynomial in positive exponents. */ public override val LabeledPolynomial.countOfVariables: Int get() = variables.size - /** - * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. - */ - override fun LabeledPolynomial.isConstant(): Boolean = - coefficients.all { (degs, c) -> degs.isEmpty() || c.isZero() } - /** - * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. - */ - override fun LabeledPolynomial.isNonZeroConstant(): Boolean = - with(coefficients) { - var foundAbsoluteTermAndItIsNotZero = false - for ((degs, c) in this) { - if (degs.isNotEmpty()) if (c.isNotZero()) return@with false - else { - if (c.isZero()) return@with false - else foundAbsoluteTermAndItIsNotZero = true - } - } - foundAbsoluteTermAndItIsNotZero - } - /** - * If polynomial is a constant polynomial represents and returns it as constant. - * Otherwise, (when the polynomial is not constant polynomial) returns `null`. - */ - override fun LabeledPolynomial.asConstantOrNull(): C? = - with(coefficients) { - if(isConstant()) getOrElse(emptyMap()) { constantZero } - else null - } - // @Suppress("NOTHING_TO_INLINE") // public inline fun LabeledPolynomial.substitute(argument: Map): LabeledPolynomial = this.substitute(ring, argument) // @Suppress("NOTHING_TO_INLINE") @@ -719,33 +632,4 @@ public class LabeledPolynomialSpace>( // @Suppress("NOTHING_TO_INLINE") // @JvmName("invokePolynomial") // public inline operator fun LabeledPolynomial.invoke(argument: Map>): LabeledPolynomial = this.substitute(ring, argument) - - // TODO: Move to other internal utilities with context receiver - @JvmName("applyAndRemoveZerosInternal") - internal fun MutableMap, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : MutableMap, C> { - contract { - callsInPlace(block, InvocationKind.EXACTLY_ONCE) - } - block() - for ((degs, c) in this) if (c.isZero()) this.remove(degs) - return this - } - internal fun Map, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : Map, C> = - toMutableMap().applyAndRemoveZeros(block) - @OptIn(ExperimentalTypeInference::class) - internal inline fun buildCoefficients(@BuilderInference builderAction: MutableMap, C>.() -> Unit): Map, C> { - contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } - return buildMap { - builderAction() - for ((degs, c) in this) if (c.isZero()) this.remove(degs) - } - } - @OptIn(ExperimentalTypeInference::class) - internal inline fun buildCoefficients(capacity: Int, @BuilderInference builderAction: MutableMap, C>.() -> Unit): Map, C> { - contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } - return buildMap(capacity) { - builderAction() - for ((degs, c) in this) if (c.isZero()) this.remove(degs) - } - } } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt index 00dd3bb47..0f46520dc 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt @@ -19,45 +19,35 @@ public class LabeledRationalFunction( // Waiting for context receivers :( TODO: Replace with context receivers when they will be available -@Suppress("FunctionName") -internal fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numerator: LabeledPolynomial, denominator: LabeledPolynomial): LabeledRationalFunction = - if (denominator.isZero()) throw ArithmeticException("/ by zero") - else LabeledRationalFunction(numerator, denominator) -@Suppress("FunctionName") -internal fun > A.LabeledRationalFunction(numerator: LabeledPolynomial, denominator: LabeledPolynomial): LabeledRationalFunction = - if (denominator.coefficients.values.all { it == zero }) throw ArithmeticException("/ by zero") - else LabeledRationalFunction(numerator, denominator) @Suppress("FunctionName") public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): LabeledRationalFunction = - if (denominatorCoefficients.values.all { it == zero }) throw ArithmeticException("/ by zero") - else LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients), - LabeledPolynomial(denominatorCoefficients) + LabeledRationalFunction( + LabeledPolynomial(numeratorCoefficients, toCheckInput = true), + LabeledPolynomial(denominatorCoefficients, toCheckInput = true) ) @Suppress("FunctionName") public fun > A.LabeledRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): LabeledRationalFunction = - if (denominatorCoefficients.values.all { it == zero }) throw ArithmeticException("/ by zero") - else LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients), - LabeledPolynomial(denominatorCoefficients) + LabeledRationalFunction( + LabeledPolynomial(numeratorCoefficients, toCheckInput = true), + LabeledPolynomial(denominatorCoefficients, toCheckInput = true) ) @Suppress("FunctionName") public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numerator: LabeledPolynomial): LabeledRationalFunction = LabeledRationalFunction(numerator, polynomialOne) @Suppress("FunctionName") public fun > A.LabeledRationalFunction(numerator: LabeledPolynomial): LabeledRationalFunction = - LabeledRationalFunction(numerator, LabeledPolynomial(mapOf(emptyMap() to one))) + LabeledRationalFunction(numerator, LabeledPolynomial(mapOf(emptyMap() to one), toCheckInput = false)) @Suppress("FunctionName") public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numeratorCoefficients: Map, C>): LabeledRationalFunction = LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients), + LabeledPolynomial(numeratorCoefficients, toCheckInput = true), polynomialOne ) @Suppress("FunctionName") public fun > A.LabeledRationalFunction(numeratorCoefficients: Map, C>): LabeledRationalFunction = LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients), - LabeledPolynomial(mapOf(emptyMap() to one)) + LabeledPolynomial(numeratorCoefficients, toCheckInput = true), + LabeledPolynomial(mapOf(emptyMap() to one), toCheckInput = false) ) public class LabeledRationalFunctionSpace>( @@ -82,38 +72,16 @@ public class LabeledRationalFunctionSpace>( numerator: LabeledPolynomial, denominator: LabeledPolynomial ): LabeledRationalFunction = - LabeledRationalFunction(numerator, denominator) + LabeledRationalFunction(numerator, denominator) /** * Instance of zero rational function (zero of the rational functions ring). */ - public override val zero: LabeledRationalFunction = LabeledRationalFunction(polynomialZero, polynomialOne) + public override val zero: LabeledRationalFunction = LabeledRationalFunction(polynomialZero, polynomialOne) /** * Instance of unit polynomial (unit of the rational functions ring). */ - public override val one: LabeledRationalFunction = LabeledRationalFunction(polynomialOne, polynomialOne) - - /** - * Checks equality of the rational functions. - */ - public override infix fun LabeledRationalFunction.equalsTo(other: LabeledRationalFunction): Boolean { - if (this === other) return true - - if (numerator.isZero() != other.numerator.isZero()) return false - - val variables = this.variables union other.variables - val thisNumeratorDegrees = this.numerator.degrees - val thisDenominatorDegrees = this.denominator.degrees - val otherNumeratorDegrees = other.numerator.degrees - val otherDenominatorDegrees = other.denominator.degrees - for (variable in variables) - if ( - thisNumeratorDegrees.getOrElse(variable) { 0u } + otherDenominatorDegrees.getOrElse(variable) { 0u } - != thisDenominatorDegrees.getOrElse(variable) { 0u } + otherNumeratorDegrees.getOrElse(variable) { 0u } - ) return false - - return numerator * other.denominator equalsTo other.numerator * denominator - } + public override val one: LabeledRationalFunction = LabeledRationalFunction(polynomialOne, polynomialOne) // TODO: Разобрать diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt index 90e9cde69..711d2bb49 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt @@ -91,13 +91,9 @@ public open class ListPolynomialSpace>( .toMutableList() .apply { val result = getOrElse(0) { constantZero } + other - val isResultZero = result.isZero() - when { - size == 0 && !isResultZero -> add(result) - size > 1 || !isResultZero -> this[0] = result - else -> clear() - } + if(size == 0) add(result) + else this[0] = result } ) /** @@ -113,13 +109,9 @@ public open class ListPolynomialSpace>( .toMutableList() .apply { val result = getOrElse(0) { constantZero } - other - val isResultZero = result.isZero() - when { - size == 0 && !isResultZero -> add(result) - size > 1 || !isResultZero -> this[0] = result - else -> clear() - } + if(size == 0) add(result) + else this[0] = result } ) /** @@ -131,7 +123,8 @@ public open class ListPolynomialSpace>( if (other == 0) zero else ListPolynomial( coefficients - .applyAndRemoveZeros { + .toMutableList() + .apply { for (deg in indices) this[deg] = this[deg] * other } ) @@ -149,13 +142,9 @@ public open class ListPolynomialSpace>( .toMutableList() .apply { val result = this@plus + getOrElse(0) { constantZero } - val isResultZero = result.isZero() - when { - size == 0 && !isResultZero -> add(result) - size > 1 || !isResultZero -> this[0] = result - else -> clear() - } + if(size == 0) add(result) + else this[0] = result } ) /** @@ -173,13 +162,9 @@ public open class ListPolynomialSpace>( forEachIndexed { index, c -> if (index != 0) this[index] = -c } val result = this@minus - getOrElse(0) { constantZero } - val isResultZero = result.isZero() - when { - size == 0 && !isResultZero -> add(result) - size > 1 || !isResultZero -> this[0] = result - else -> clear() - } + if(size == 0) add(result) + else this[0] = result } ) /** @@ -191,7 +176,8 @@ public open class ListPolynomialSpace>( if (this == 0) zero else ListPolynomial( other.coefficients - .applyAndRemoveZeros { + .toMutableList() + .apply { for (deg in indices) this[deg] = this@times * this[deg] } ) @@ -205,20 +191,15 @@ public open class ListPolynomialSpace>( * Returns sum of the constant represented as polynomial and the polynomial. */ public override operator fun C.plus(other: ListPolynomial): ListPolynomial = - if (this.isZero()) other - else with(other.coefficients) { + with(other.coefficients) { if (isEmpty()) ListPolynomial(listOf(this@plus)) else ListPolynomial( toMutableList() .apply { val result = if (size == 0) this@plus else this@plus + get(0) - val isResultZero = result.isZero() - when { - size == 0 && !isResultZero -> add(result) - size > 1 || !isResultZero -> this[0] = result - else -> clear() - } + if(size == 0) add(result) + else this[0] = result } ) } @@ -226,8 +207,7 @@ public open class ListPolynomialSpace>( * Returns difference between the constant represented as polynomial and the polynomial. */ public override operator fun C.minus(other: ListPolynomial): ListPolynomial = - if (this.isZero()) other - else with(other.coefficients) { + with(other.coefficients) { if (isEmpty()) ListPolynomial(listOf(this@minus)) else ListPolynomial( toMutableList() @@ -235,13 +215,9 @@ public open class ListPolynomialSpace>( forEachIndexed { index, c -> if (index != 0) this[index] = -c } val result = if (size == 0) this@minus else this@minus - get(0) - val isResultZero = result.isZero() - when { - size == 0 && !isResultZero -> add(result) - size > 1 || !isResultZero -> this[0] = result - else -> clear() - } + if(size == 0) add(result) + else this[0] = result } ) } @@ -249,10 +225,10 @@ public open class ListPolynomialSpace>( * Returns product of the constant represented as polynomial and the polynomial. */ public override operator fun C.times(other: ListPolynomial): ListPolynomial = - if (this.isZero()) other - else ListPolynomial( + ListPolynomial( other.coefficients - .applyAndRemoveZeros { + .toMutableList() + .apply { for (deg in indices) this[deg] = this@times * this[deg] } ) @@ -261,20 +237,15 @@ public open class ListPolynomialSpace>( * Returns sum of the constant represented as polynomial and the polynomial. */ public override operator fun ListPolynomial.plus(other: C): ListPolynomial = - if (other.isZero()) this - else with(coefficients) { + with(coefficients) { if (isEmpty()) ListPolynomial(listOf(other)) else ListPolynomial( toMutableList() .apply { val result = if (size == 0) other else get(0) + other - val isResultZero = result.isZero() - when { - size == 0 && !isResultZero -> add(result) - size > 1 || !isResultZero -> this[0] = result - else -> clear() - } + if(size == 0) add(result) + else this[0] = result } ) } @@ -282,20 +253,15 @@ public open class ListPolynomialSpace>( * Returns difference between the constant represented as polynomial and the polynomial. */ public override operator fun ListPolynomial.minus(other: C): ListPolynomial = - if (other.isZero()) this - else with(coefficients) { + with(coefficients) { if (isEmpty()) ListPolynomial(listOf(-other)) else ListPolynomial( toMutableList() .apply { val result = if (size == 0) other else get(0) - other - val isResultZero = result.isZero() - when { - size == 0 && !isResultZero -> add(result) - size > 1 || !isResultZero -> this[0] = result - else -> clear() - } + if(size == 0) add(result) + else this[0] = result } ) } @@ -303,10 +269,10 @@ public open class ListPolynomialSpace>( * Returns product of the constant represented as polynomial and the polynomial. */ public override operator fun ListPolynomial.times(other: C): ListPolynomial = - if (other.isZero()) this - else ListPolynomial( + ListPolynomial( coefficients - .applyAndRemoveZeros { + .toMutableList() + .apply { for (deg in indices) this[deg] = this[deg] * other } ) @@ -314,9 +280,7 @@ public open class ListPolynomialSpace>( /** * Converts the constant [value] to polynomial. */ - public override fun number(value: C): ListPolynomial = - if (value.isZero()) zero - else ListPolynomial(value) + public override fun number(value: C): ListPolynomial = ListPolynomial(value) /** * Returns negation of the polynomial. @@ -330,7 +294,7 @@ public open class ListPolynomialSpace>( val thisDegree = degree val otherDegree = other.degree return ListPolynomial( - Coefficients(max(thisDegree, otherDegree) + 1) { + List(max(thisDegree, otherDegree) + 1) { when { it > thisDegree -> other.coefficients[it] it > otherDegree -> coefficients[it] @@ -346,7 +310,7 @@ public open class ListPolynomialSpace>( val thisDegree = degree val otherDegree = other.degree return ListPolynomial( - Coefficients(max(thisDegree, otherDegree) + 1) { + List(max(thisDegree, otherDegree) + 1) { when { it > thisDegree -> -other.coefficients[it] it > otherDegree -> coefficients[it] @@ -361,39 +325,15 @@ public open class ListPolynomialSpace>( public override operator fun ListPolynomial.times(other: ListPolynomial): ListPolynomial { val thisDegree = degree val otherDegree = other.degree - return when { - thisDegree == -1 -> zero - otherDegree == -1 -> zero - else -> - ListPolynomial( - Coefficients(thisDegree + otherDegree + 1) { d -> - (max(0, d - otherDegree)..min(thisDegree, d)) - .map { coefficients[it] * other.coefficients[d - it] } - .reduce { acc, rational -> acc + rational } - } - ) - } + return ListPolynomial( + List(thisDegree + otherDegree + 1) { d -> + (max(0, d - otherDegree)..min(thisDegree, d)) + .map { coefficients[it] * other.coefficients[d - it] } + .reduce { acc, rational -> acc + rational } + } + ) } - /** - * Check if the instant is zero polynomial. - */ - public override fun ListPolynomial.isZero(): Boolean = coefficients.all { it.isZero() } - /** - * Check if the instant is unit polynomial. - */ - public override fun ListPolynomial.isOne(): Boolean = - with(coefficients) { - isNotEmpty() && withIndex().all { (index, c) -> if (index == 0) c.isOne() else c.isZero() } - } - /** - * Check if the instant is minus unit polynomial. - */ - public override fun ListPolynomial.isMinusOne(): Boolean = - with(coefficients) { - isNotEmpty() && withIndex().all { (index, c) -> if (index == 0) c.isMinusOne() else c.isZero() } - } - /** * Instance of zero polynomial (zero of the polynomial ring). */ @@ -403,34 +343,11 @@ public open class ListPolynomialSpace>( */ override val one: ListPolynomial = ListPolynomial(listOf(constantOne)) - /** - * Checks equality of the polynomials. - */ - public override infix fun ListPolynomial.equalsTo(other: ListPolynomial): Boolean = - when { - this === other -> true - this.degree == other.degree -> (0..degree).all { coefficients[it] == other.coefficients[it] } - else -> false - } - /** * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is * zero, degree is -1. */ - public override val ListPolynomial.degree: Int get() = coefficients.indexOfLast { it != constantZero } - - /** - * If polynomial is a constant polynomial represents and returns it as constant. - * Otherwise, (when the polynomial is not constant polynomial) returns `null`. - */ - public override fun ListPolynomial.asConstantOrNull(): C? = - with(coefficients) { - when { - isEmpty() -> constantZero - withIndex().all { (index, c) -> index == 0 || c.isZero() } -> first() - else -> null - } - } + public override val ListPolynomial.degree: Int get() = coefficients.lastIndex @Suppress("NOTHING_TO_INLINE") public inline fun ListPolynomial.substitute(argument: C): C = this.substitute(ring, argument) @@ -451,44 +368,6 @@ public open class ListPolynomialSpace>( public inline operator fun ListPolynomial.invoke(argument: C): C = this.substitute(ring, argument) @Suppress("NOTHING_TO_INLINE") public inline operator fun ListPolynomial.invoke(argument: ListPolynomial): ListPolynomial = this.substitute(ring, argument) - - // TODO: Move to other internal utilities with context receiver - @JvmName("applyAndRemoveZerosInternal") - internal inline fun MutableList.applyAndRemoveZeros(block: MutableList.() -> Unit) : MutableList { - contract { - callsInPlace(block, InvocationKind.EXACTLY_ONCE) - } - block() - while (isNotEmpty() && elementAt(lastIndex).isZero()) removeAt(lastIndex) - return this - } - internal inline fun List.applyAndRemoveZeros(block: MutableList.() -> Unit) : List = - toMutableList().applyAndRemoveZeros(block) - @Suppress("FunctionName") - internal inline fun MutableCoefficients(size: Int, init: (index: Int) -> C): MutableList { - val list = ArrayList(size) - repeat(size) { index -> list.add(init(index)) } - with(list) { while (isNotEmpty() && elementAt(lastIndex).isZero()) removeAt(lastIndex) } - return list - } - @Suppress("FunctionName") - internal inline fun Coefficients(size: Int, init: (index: Int) -> C): List = MutableCoefficients(size, init) - @OptIn(ExperimentalTypeInference::class) - internal inline fun buildCoefficients(@BuilderInference builderAction: MutableList.() -> Unit): List { - contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } - return buildList { - builderAction() - while (isNotEmpty() && elementAt(lastIndex).isZero()) removeAt(lastIndex) - } - } - @OptIn(ExperimentalTypeInference::class) - internal inline fun buildCoefficients(capacity: Int, @BuilderInference builderAction: MutableList.() -> Unit): List { - contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } - return buildList(capacity) { - builderAction() - while (isNotEmpty() && elementAt(lastIndex).isZero()) removeAt(lastIndex) - } - } } /** diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt index 67c7e9fa2..f62d1857f 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt @@ -8,7 +8,7 @@ package space.kscience.kmath.functions import space.kscience.kmath.operations.Ring -public data class ListRationalFunction internal constructor ( +public data class ListRationalFunction( public override val numerator: ListPolynomial, public override val denominator: ListPolynomial ) : RationalFunction> { @@ -17,25 +17,15 @@ public data class ListRationalFunction internal constructor ( // Waiting for context receivers :( TODO: Replace with context receivers when they will be available -@Suppress("FunctionName") -internal fun > ListRationalFunctionSpace.ListRationalFunction(numerator: ListPolynomial, denominator: ListPolynomial): ListRationalFunction = - if (denominator.isZero()) throw ArithmeticException("/ by zero") - else ListRationalFunction(numerator, denominator) -@Suppress("FunctionName") -internal fun > A.ListRationalFunction(numerator: ListPolynomial, denominator: ListPolynomial): ListRationalFunction = - if (denominator.coefficients.all { it == zero }) throw ArithmeticException("/ by zero") - else ListRationalFunction(numerator, denominator) @Suppress("FunctionName") public fun > ListRationalFunctionSpace.ListRationalFunction(numeratorCoefficients: List, denominatorCoefficients: List, reverse: Boolean = false): ListRationalFunction = - if (denominatorCoefficients.all { it == zero }) throw ArithmeticException("/ by zero") - else ListRationalFunction( + ListRationalFunction( ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), ListPolynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } ) ) @Suppress("FunctionName") public fun > A.ListRationalFunction(numeratorCoefficients: List, denominatorCoefficients: List, reverse: Boolean = false): ListRationalFunction = - if (denominatorCoefficients.all { it == zero }) throw ArithmeticException("/ by zero") - else ListRationalFunction( + ListRationalFunction( ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), ListPolynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } ) ) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index 80998d6bf..51f316c5d 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -58,6 +58,8 @@ internal fun List.cleanUp() = subList(0, indexOfLast { it != 0U } + 1) @Suppress("FunctionName", "NOTHING_TO_INLINE") internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(coefs, toCheckInput) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(coefs, toCheckInput) @Suppress("FunctionName") internal fun > A.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial { if (!toCheckInput) return NumberedPolynomial(coefs) @@ -70,13 +72,13 @@ internal fun > A.NumberedPolynomial(coefs: Map, C>, toC fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value } - return NumberedPolynomial( - fixedCoefs.filterValues { it != zero } - ) + return NumberedPolynomial(fixedCoefs) } @Suppress("FunctionName", "NOTHING_TO_INLINE") internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs, toCheckInput) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs, toCheckInput) @Suppress("FunctionName") internal fun > A.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial { if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) @@ -89,13 +91,13 @@ internal fun > A.NumberedPolynomial(pairs: Collection( - fixedCoefs.filterValues { it != zero } - ) + return NumberedPolynomial(fixedCoefs) } @Suppress("FunctionName", "NOTHING_TO_INLINE") internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs = pairs, toCheckInput = toCheckInput) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs = pairs, toCheckInput = toCheckInput) @Suppress("FunctionName") internal fun > A.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial { if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) @@ -108,25 +110,29 @@ internal fun > A.NumberedPolynomial(vararg pairs: Pair, fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value } - return NumberedPolynomial( - fixedCoefs.filterValues { it != zero } - ) + return NumberedPolynomial(fixedCoefs) } @Suppress("FunctionName") public fun > A.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) @Suppress("FunctionName") public fun > NumberedPolynomialSpace.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) +@Suppress("FunctionName") +public fun > NumberedRationalFunctionSpace.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) @Suppress("FunctionName") public fun > A.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) @Suppress("FunctionName") public fun > NumberedPolynomialSpace.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > NumberedRationalFunctionSpace.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) @Suppress("FunctionName") public fun > A.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) @Suppress("FunctionName") public fun > NumberedPolynomialSpace.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > NumberedRationalFunctionSpace.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) //context(A) //public fun > Symbol.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(mapOf(this to 1u) to one)) @@ -211,10 +217,7 @@ public open class NumberedPolynomialSpace>( .apply { val degs = emptyList() - val result = getOrElse(degs) { constantZero } + other - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = getOrElse(degs) { constantZero } + other } ) /** @@ -231,10 +234,7 @@ public open class NumberedPolynomialSpace>( .apply { val degs = emptyList() - val result = getOrElse(degs) { constantZero } - other - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = getOrElse(degs) { constantZero } - other } ) /** @@ -246,7 +246,8 @@ public open class NumberedPolynomialSpace>( if (other == 0) zero else NumberedPolynomial( coefficients - .applyAndRemoveZeros { + .toMutableMap() + .apply { for (degs in keys) this[degs] = this[degs]!! * other } ) @@ -265,10 +266,7 @@ public open class NumberedPolynomialSpace>( .apply { val degs = emptyList() - val result = this@plus + getOrElse(degs) { constantZero } - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = this@plus + getOrElse(degs) { constantZero } } ) /** @@ -285,10 +283,7 @@ public open class NumberedPolynomialSpace>( .apply { val degs = emptyList() - val result = this@minus - getOrElse(degs) { constantZero } - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = this@minus - getOrElse(degs) { constantZero } } ) /** @@ -300,7 +295,8 @@ public open class NumberedPolynomialSpace>( if (this == 0) zero else NumberedPolynomial( other.coefficients - .applyAndRemoveZeros { + .toMutableMap() + .apply { for (degs in keys) this[degs] = this@times * this[degs]!! } ) @@ -314,18 +310,14 @@ public open class NumberedPolynomialSpace>( * Returns sum of the constant represented as polynomial and the polynomial. */ override operator fun C.plus(other: NumberedPolynomial): NumberedPolynomial = - if (this.isZero()) other - else with(other.coefficients) { + with(other.coefficients) { if (isEmpty()) NumberedPolynomial(mapOf(emptyList() to this@plus)) else NumberedPolynomial( toMutableMap() .apply { val degs = emptyList() - val result = this@plus + getOrElse(degs) { constantZero } - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = this@plus + getOrElse(degs) { constantZero } } ) } @@ -333,8 +325,7 @@ public open class NumberedPolynomialSpace>( * Returns difference between the constant represented as polynomial and the polynomial. */ override operator fun C.minus(other: NumberedPolynomial): NumberedPolynomial = - if (this.isZero()) -other - else with(other.coefficients) { + with(other.coefficients) { if (isEmpty()) NumberedPolynomial(mapOf(emptyList() to this@minus)) else NumberedPolynomial( toMutableMap() @@ -343,10 +334,7 @@ public open class NumberedPolynomialSpace>( val degs = emptyList() - val result = this@minus - getOrElse(degs) { constantZero } - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = this@minus - getOrElse(degs) { constantZero } } ) } @@ -354,10 +342,10 @@ public open class NumberedPolynomialSpace>( * Returns product of the constant represented as polynomial and the polynomial. */ override operator fun C.times(other: NumberedPolynomial): NumberedPolynomial = - if (this.isZero()) zero - else NumberedPolynomial( + NumberedPolynomial( other.coefficients - .applyAndRemoveZeros { + .toMutableMap() + .apply { for (degs in keys) this[degs] = this@times * this[degs]!! } ) @@ -366,18 +354,14 @@ public open class NumberedPolynomialSpace>( * Returns sum of the constant represented as polynomial and the polynomial. */ override operator fun NumberedPolynomial.plus(other: C): NumberedPolynomial = - if (other.isZero()) this - else with(coefficients) { + with(coefficients) { if (isEmpty()) NumberedPolynomial(mapOf(emptyList() to other)) else NumberedPolynomial( toMutableMap() .apply { val degs = emptyList() - val result = getOrElse(degs) { constantZero } + other - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = getOrElse(degs) { constantZero } + other } ) } @@ -385,18 +369,14 @@ public open class NumberedPolynomialSpace>( * Returns difference between the constant represented as polynomial and the polynomial. */ override operator fun NumberedPolynomial.minus(other: C): NumberedPolynomial = - if (other.isZero()) this - else with(coefficients) { + with(coefficients) { if (isEmpty()) NumberedPolynomial(mapOf(emptyList() to other)) else NumberedPolynomial( toMutableMap() .apply { val degs = emptyList() - val result = getOrElse(degs) { constantZero } - other - - if (result.isZero()) remove(degs) - else this[degs] = result + this[degs] = getOrElse(degs) { constantZero } - other } ) } @@ -404,10 +384,10 @@ public open class NumberedPolynomialSpace>( * Returns product of the constant represented as polynomial and the polynomial. */ override operator fun NumberedPolynomial.times(other: C): NumberedPolynomial = - if (other.isZero()) zero - else NumberedPolynomial( + NumberedPolynomial( coefficients - .applyAndRemoveZeros { + .toMutableMap() + .apply { for (degs in keys) this[degs] = this[degs]!! * other } ) @@ -416,8 +396,7 @@ public open class NumberedPolynomialSpace>( * Converts the constant [value] to polynomial. */ public override fun number(value: C): NumberedPolynomial = - if (value == 0) zero - else NumberedPolynomial(mapOf(emptyList() to value)) + NumberedPolynomial(mapOf(emptyList() to value)) /** * Returns negation of the polynomial. @@ -431,7 +410,7 @@ public open class NumberedPolynomialSpace>( */ override operator fun NumberedPolynomial.plus(other: NumberedPolynomial): NumberedPolynomial = NumberedPolynomial( - buildCoefficients(coefficients.size + other.coefficients.size) { + buildMap(coefficients.size + other.coefficients.size) { other.coefficients.mapValuesTo(this) { it.value } other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value } } @@ -441,7 +420,7 @@ public open class NumberedPolynomialSpace>( */ override operator fun NumberedPolynomial.minus(other: NumberedPolynomial): NumberedPolynomial = NumberedPolynomial( - buildCoefficients(coefficients.size + other.coefficients.size) { + buildMap(coefficients.size + other.coefficients.size) { other.coefficients.mapValuesTo(this) { it.value } other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value } } @@ -450,57 +429,17 @@ public open class NumberedPolynomialSpace>( * Returns product of the polynomials. */ override operator fun NumberedPolynomial.times(other: NumberedPolynomial): NumberedPolynomial = - when { - isZero() -> zero - other.isZero() -> zero - else -> - NumberedPolynomial( - buildCoefficients(coefficients.size * other.coefficients.size) { - for ((degs1, c1) in coefficients) for ((degs2, c2) in other.coefficients) { - val degs = - (0..max(degs1.lastIndex, degs2.lastIndex)) - .map { degs1.getOrElse(it) { 0U } + degs2.getOrElse(it) { 0U } } - val c = c1 * c2 - this[degs] = if (degs in this) this[degs]!! + c else c - } - } - ) - } - - /** - * Check if the instant is zero polynomial. - */ - public override fun NumberedPolynomial.isZero(): Boolean = coefficients.values.all { it.isZero() } - /** - * Check if the instant is unit polynomial. - */ - public override fun NumberedPolynomial.isOne(): Boolean = - with(coefficients) { - var foundAbsoluteTermAndItIsOne = false - for ((degs, c) in this) { - if (degs.isNotEmpty()) if (c.isNotZero()) return@with false - else { - if (c.isNotOne()) return@with false - else foundAbsoluteTermAndItIsOne = true + NumberedPolynomial( + buildMap(coefficients.size * other.coefficients.size) { + for ((degs1, c1) in coefficients) for ((degs2, c2) in other.coefficients) { + val degs = + (0..max(degs1.lastIndex, degs2.lastIndex)) + .map { degs1.getOrElse(it) { 0U } + degs2.getOrElse(it) { 0U } } + val c = c1 * c2 + this[degs] = if (degs in this) this[degs]!! + c else c } } - foundAbsoluteTermAndItIsOne - } - /** - * Check if the instant is minus unit polynomial. - */ - public override fun NumberedPolynomial.isMinusOne(): Boolean = - with(coefficients) { - var foundAbsoluteTermAndItIsMinusOne = false - for ((degs, c) in this) { - if (degs.isNotEmpty()) if (c.isNotZero()) return@with false - else { - if (c.isNotMinusOne()) return@with false - else foundAbsoluteTermAndItIsMinusOne = true - } - } - foundAbsoluteTermAndItIsMinusOne - } + ) /** * Instance of zero polynomial (zero of the polynomial ring). @@ -516,28 +455,18 @@ public open class NumberedPolynomialSpace>( ) ) - /** - * Checks equality of the polynomials. - */ - override infix fun NumberedPolynomial.equalsTo(other: NumberedPolynomial): Boolean = - when { - this === other -> true - else -> coefficients.size == other.coefficients.size && - coefficients.all { (key, value) -> with(other.coefficients) { key in this && this[key] == value } } - } - /** * Maximal index (ID) of variable occurring in the polynomial with positive power. If there is no such variable, * the result is `-1`. */ public val NumberedPolynomial.lastVariable: Int - get() = coefficients.entries.maxOfOrNull { (degs, c) -> if (c.isZero()) -1 else degs.lastIndex } ?: -1 + get() = coefficients.entries.maxOfOrNull { (degs, _) -> degs.lastIndex } ?: -1 /** * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is * zero, degree is -1. */ override val NumberedPolynomial.degree: Int - get() = coefficients.entries.maxOfOrNull { (degs, c) -> if (c.isZero()) -1 else degs.sum().toInt() } ?: -1 + get() = coefficients.entries.maxOfOrNull { (degs, _) -> degs.sum().toInt() } ?: -1 /** * List that associates indices of variables (that appear in the polynomial in positive exponents) with their most * exponents in which the variables are appeared in the polynomial. @@ -548,8 +477,8 @@ public open class NumberedPolynomialSpace>( public val NumberedPolynomial.degrees: List get() = MutableList(lastVariable + 1) { 0u }.apply { - coefficients.entries.forEach { (degs, c) -> - if (c.isNotZero()) degs.forEachIndexed { index, deg -> + coefficients.entries.forEach { (degs, _) -> + degs.forEachIndexed { index, deg -> this[index] = max(this[index], deg) } } @@ -558,13 +487,13 @@ public open class NumberedPolynomialSpace>( * Counts degree of the polynomial by the specified [variable]. */ public fun NumberedPolynomial.degreeBy(variable: Int): UInt = - coefficients.entries.maxOfOrNull { (degs, c) -> if (c.isZero()) 0u else degs.getOrElse(variable) { 0u } } ?: 0u + coefficients.entries.maxOfOrNull { (degs, _) -> degs.getOrElse(variable) { 0u } } ?: 0u /** * Counts degree of the polynomial by the specified [variables]. */ public fun NumberedPolynomial.degreeBy(variables: Collection): UInt = - coefficients.entries.maxOfOrNull { (degs, c) -> - if (c.isZero()) 0u else degs.withIndex().filter { (index, _) -> index in variables }.sumOf { it.value } + coefficients.entries.maxOfOrNull { (degs, _) -> + degs.withIndex().filter { (index, _) -> index in variables }.sumOf { it.value } } ?: 0u /** * Count of variables occurring in the polynomial with positive power. If there is no such variable, @@ -573,43 +502,13 @@ public open class NumberedPolynomialSpace>( public val NumberedPolynomial.countOfVariables: Int get() = MutableList(lastVariable + 1) { false }.apply { - coefficients.entries.forEach { (degs, c) -> - if (c.isNotZero()) degs.forEachIndexed { index, deg -> + coefficients.entries.forEach { (degs, _) -> + degs.forEachIndexed { index, deg -> if (deg != 0u) this[index] = true } } }.count { it } - /** - * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. - */ - override fun NumberedPolynomial.isConstant(): Boolean = - coefficients.all { (degs, c) -> degs.isEmpty() || c.isZero() } - /** - * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. - */ - override fun NumberedPolynomial.isNonZeroConstant(): Boolean = - with(coefficients) { - var foundAbsoluteTermAndItIsNotZero = false - for ((degs, c) in this) { - if (degs.isNotEmpty()) if (c.isNotZero()) return@with false - else { - if (c.isZero()) return@with false - else foundAbsoluteTermAndItIsNotZero = true - } - } - foundAbsoluteTermAndItIsNotZero - } - /** - * If polynomial is a constant polynomial represents and returns it as constant. - * Otherwise, (when the polynomial is not constant polynomial) returns `null`. - */ - override fun NumberedPolynomial.asConstantOrNull(): C? = - with(coefficients) { - if(isConstant()) getOrElse(emptyList()) { constantZero } - else null - } - @Suppress("NOTHING_TO_INLINE") public inline fun NumberedPolynomial.substitute(argument: Map): NumberedPolynomial = this.substitute(ring, argument) @Suppress("NOTHING_TO_INLINE") @@ -629,35 +528,6 @@ public open class NumberedPolynomialSpace>( @JvmName("invokePolynomial") public inline operator fun NumberedPolynomial.invoke(argument: Map>): NumberedPolynomial = this.substitute(ring, argument) - // TODO: Move to other internal utilities with context receiver - @JvmName("applyAndRemoveZerosInternal") - internal fun MutableMap, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : MutableMap, C> { - contract { - callsInPlace(block, InvocationKind.EXACTLY_ONCE) - } - block() - for ((degs, c) in this) if (c.isZero()) this.remove(degs) - return this - } - internal fun Map, C>.applyAndRemoveZeros(block: MutableMap, C>.() -> Unit) : Map, C> = - toMutableMap().applyAndRemoveZeros(block) - @OptIn(ExperimentalTypeInference::class) - internal inline fun buildCoefficients(@BuilderInference builderAction: MutableMap, C>.() -> Unit): Map, C> { - contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } - return buildMap { - builderAction() - for ((degs, c) in this) if (c.isZero()) this.remove(degs) - } - } - @OptIn(ExperimentalTypeInference::class) - internal inline fun buildCoefficients(capacity: Int, @BuilderInference builderAction: MutableMap, C>.() -> Unit): Map, C> { - contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } - return buildMap(capacity) { - builderAction() - for ((degs, c) in this) if (c.isZero()) this.remove(degs) - } - } - // TODO: Move to other constructors with context receiver public fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(emptyList() to this)) } \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt index 2a4d942a6..b4d9f1d91 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt @@ -19,45 +19,35 @@ public class NumberedRationalFunction internal constructor( // Waiting for context receivers :( TODO: Replace with context receivers when they will be available -@Suppress("FunctionName") -internal fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numerator: NumberedPolynomial, denominator: NumberedPolynomial): NumberedRationalFunction = - if (denominator.isZero()) throw ArithmeticException("/ by zero") - else NumberedRationalFunction(numerator, denominator) -@Suppress("FunctionName") -internal fun > A.NumberedRationalFunction(numerator: NumberedPolynomial, denominator: NumberedPolynomial): NumberedRationalFunction = - if (denominator.coefficients.values.all { it == zero }) throw ArithmeticException("/ by zero") - else NumberedRationalFunction(numerator, denominator) @Suppress("FunctionName") public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): NumberedRationalFunction = - if (denominatorCoefficients.values.all { it == zero }) throw ArithmeticException("/ by zero") - else NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients), - NumberedPolynomial(denominatorCoefficients) + NumberedRationalFunction( + NumberedPolynomial(numeratorCoefficients, toCheckInput = true), + NumberedPolynomial(denominatorCoefficients, toCheckInput = true) ) @Suppress("FunctionName") public fun > A.NumberedRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): NumberedRationalFunction = - if (denominatorCoefficients.values.all { it == zero }) throw ArithmeticException("/ by zero") - else NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients), - NumberedPolynomial(denominatorCoefficients) + NumberedRationalFunction( + NumberedPolynomial(numeratorCoefficients, toCheckInput = true), + NumberedPolynomial(denominatorCoefficients, toCheckInput = true) ) @Suppress("FunctionName") public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numerator: NumberedPolynomial): NumberedRationalFunction = NumberedRationalFunction(numerator, polynomialOne) @Suppress("FunctionName") public fun > A.NumberedRationalFunction(numerator: NumberedPolynomial): NumberedRationalFunction = - NumberedRationalFunction(numerator, NumberedPolynomial(mapOf(emptyList() to one))) + NumberedRationalFunction(numerator, NumberedPolynomial(mapOf(emptyList() to one), toCheckInput = false)) @Suppress("FunctionName") public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numeratorCoefficients: Map, C>): NumberedRationalFunction = NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients), + NumberedPolynomial(numeratorCoefficients, toCheckInput = true), polynomialOne ) @Suppress("FunctionName") public fun > A.NumberedRationalFunction(numeratorCoefficients: Map, C>): NumberedRationalFunction = NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients), - NumberedPolynomial(mapOf(emptyList() to one)) + NumberedPolynomial(numeratorCoefficients, toCheckInput = true), + NumberedPolynomial(mapOf(emptyList() to one), toCheckInput = false) ) public class NumberedRationalFunctionSpace> ( @@ -91,28 +81,6 @@ public class NumberedRationalFunctionSpace> ( */ public override val one: NumberedRationalFunction = NumberedRationalFunction(polynomialOne, polynomialOne) - /** - * Checks equality of the rational functions. - */ - public override infix fun NumberedRationalFunction.equalsTo(other: NumberedRationalFunction): Boolean { - if (this === other) return true - - if (numerator.isZero() != other.numerator.isZero()) return false - - val countOfVariables = max(this.lastVariable, other.lastVariable) - val thisNumeratorDegrees = this.numerator.degrees - val thisDenominatorDegrees = this.denominator.degrees - val otherNumeratorDegrees = other.numerator.degrees - val otherDenominatorDegrees = other.denominator.degrees - for (variable in 0 .. countOfVariables) - if ( - thisNumeratorDegrees.getOrElse(variable) { 0u } + otherDenominatorDegrees.getOrElse(variable) { 0u } - != thisDenominatorDegrees.getOrElse(variable) { 0u } + otherNumeratorDegrees.getOrElse(variable) { 0u } - ) return false - - return numerator * other.denominator equalsTo other.numerator * denominator - } - /** * Maximal index (ID) of variable occurring in the polynomial with positive power. If there is no such variable, * the result is `-1`. @@ -152,13 +120,13 @@ public class NumberedRationalFunctionSpace> ( public val NumberedRationalFunction.countOfVariables: Int get() = MutableList(lastVariable + 1) { false }.apply { - numerator.coefficients.entries.forEach { (degs, c) -> - if (c.isNotZero()) degs.forEachIndexed { index, deg -> + numerator.coefficients.entries.forEach { (degs, _) -> + degs.forEachIndexed { index, deg -> if (deg != 0u) this[index] = true } } - denominator.coefficients.entries.forEach { (degs, c) -> - if (c.isNotZero()) degs.forEachIndexed { index, deg -> + denominator.coefficients.entries.forEach { (degs, _) -> + degs.forEachIndexed { index, deg -> if (deg != 0u) this[index] = true } } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt index d44c47dd6..96e860550 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt @@ -155,31 +155,6 @@ public interface PolynomialSpace> : Ring

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

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

{ */ public override val one: P - /** - * Checks equality of the polynomials. - */ - public infix fun P.equalsTo(other: P): Boolean - /** - * Checks NOT equality of the polynomials. - */ - public infix fun P.notEqualsTo(other: P): Boolean = !(this equalsTo other) - /** * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is * zero, degree is -1. */ public val P.degree: Int - /** - * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. - */ - public fun P.isConstant(): Boolean = degree <= 0 - /** - * Checks if the instant is **not** constant polynomial (of degree no more than 0) over considered ring. - */ - public fun P.isNotConstant(): Boolean = !isConstant() - /** - * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. - */ - public fun P.isNonZeroConstant(): Boolean = degree == 0 - /** - * Checks if the instant is **not** constant non-zero polynomial (of degree no more than 0) over considered ring. - */ - public fun P.isNotNonZeroConstant(): Boolean = !isNonZeroConstant() - /** - * If polynomial is a constant polynomial represents and returns it as constant. - * Otherwise, (when the polynomial is not constant polynomial) returns `null`. - */ - public fun P.asConstantOrNull(): C? - /** - * If polynomial is a constant polynomial represents and returns it as constant. - * Otherwise, (when the polynomial is not constant polynomial) raises corresponding exception. - */ - public fun P.asConstant(): C = requireNotNull(asConstantOrNull()) { "Can not represent non-constant polynomial as a constant" } - override fun add(left: P, right: P): P = left + right override fun multiply(left: P, right: P): P = left * right } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index 9c0263c4c..374f4a936 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -222,31 +222,6 @@ public interface RationalFunctionalSpace, R: RationalFunctio @JsName("constantPower") public fun power(arg: C, exponent: UInt) : C - /** - * Check if the instant is zero constant. - */ - public fun C.isZero(): Boolean = this == constantZero - /** - * Check if the instant is NOT zero constant. - */ - public fun C.isNotZero(): Boolean = !isZero() - /** - * Check if the instant is unit constant. - */ - public fun C.isOne(): Boolean = this == constantOne - /** - * Check if the instant is NOT unit constant. - */ - public fun C.isNotOne(): Boolean = !isOne() - /** - * Check if the instant is minus unit constant. - */ - public fun C.isMinusOne(): Boolean = this == -constantOne - /** - * Check if the instant is NOT minus unit constant. - */ - public fun C.isNotMinusOne(): Boolean = !isMinusOne() - /** * Instance of zero constant (zero of the underlying ring). */ @@ -320,31 +295,6 @@ public interface RationalFunctionalSpace, R: RationalFunctio */ public fun power(arg: P, exponent: UInt) : P - /** - * Check if the instant is zero polynomial. - */ - public fun P.isZero(): Boolean = this equalsTo polynomialZero - /** - * Check if the instant is NOT zero polynomial. - */ - public fun P.isNotZero(): Boolean = !isZero() - /** - * Check if the instant is unit polynomial. - */ - public fun P.isOne(): Boolean = this equalsTo polynomialOne - /** - * Check if the instant is NOT unit polynomial. - */ - public fun P.isNotOne(): Boolean = !isOne() - /** - * Check if the instant is minus unit polynomial. - */ - public fun P.isMinusOne(): Boolean = this equalsTo -polynomialOne - /** - * Check if the instant is NOT minus unit polynomial. - */ - public fun P.isNotMinusOne(): Boolean = !isMinusOne() - /** * Instance of zero polynomial (zero of the polynomial ring). */ @@ -354,15 +304,6 @@ public interface RationalFunctionalSpace, R: RationalFunctio */ public val polynomialOne: P - /** - * Checks equality of the polynomials. - */ - public infix fun P.equalsTo(other: P): Boolean - /** - * Checks NOT equality of the polynomials. - */ - public infix fun P.notEqualsTo(other: P): Boolean = !(this equalsTo other) - /** * Returns sum of the constant represented as rational function and the rational function. */ @@ -478,31 +419,6 @@ public interface RationalFunctionalSpace, R: RationalFunctio */ public override fun power(arg: R, exponent: UInt) : R = exponentiationBySquaring(arg, exponent) - /** - * Check if the instant is zero rational function. - */ - public fun R.isZero(): Boolean = numerator equalsTo polynomialZero - /** - * Check if the instant is NOT zero rational function. - */ - public fun R.isNotZero(): Boolean = !isZero() - /** - * Check if the instant is unit rational function. - */ - public fun R.isOne(): Boolean = numerator equalsTo denominator - /** - * Check if the instant is NOT unit rational function. - */ - public fun R.isNotOne(): Boolean = !isOne() - /** - * Check if the instant is minus unit rational function. - */ - public fun R.isMinusOne(): Boolean = (numerator + denominator).isZero() - /** - * Check if the instant is NOT minus unit rational function. - */ - public fun R.isNotMinusOne(): Boolean = !isMinusOne() - /** * Instance of zero rational function (zero of the rational functions ring). */ @@ -512,54 +428,12 @@ public interface RationalFunctionalSpace, R: RationalFunctio */ public override val one: R - /** - * Checks equality of the rational functions. - */ - public infix fun R.equalsTo(other: R): Boolean = - when { - this === other -> true - numerator.isZero() != other.numerator.isZero() -> false - numeratorDegree - denominatorDegree != with(other) { numeratorDegree - denominatorDegree } -> false - else -> numerator * other.denominator equalsTo other.numerator * denominator - } - /** - * Checks NOT equality of the polynomials. - */ - public infix fun R.notEqualsTo(other: R): Boolean = !(this equalsTo other) - /** * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is * zero, degree is -1. */ public val P.degree: Int - /** - * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. - */ - public fun P.isConstant(): Boolean = degree <= 0 - /** - * Checks if the instant is **not** constant polynomial (of degree no more than 0) over considered ring. - */ - public fun P.isNotConstant(): Boolean = !isConstant() - /** - * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. - */ - public fun P.isNonZeroConstant(): Boolean = degree == 0 - /** - * Checks if the instant is **not** constant non-zero polynomial (of degree no more than 0) over considered ring. - */ - public fun P.isNotNonZeroConstant(): Boolean = !isNonZeroConstant() - /** - * If polynomial is a constant polynomial represents and returns it as constant. - * Otherwise, (when the polynomial is not constant polynomial) returns `null`. - */ - public fun P.asConstantOrNull(): C? - /** - * If polynomial is a constant polynomial represents and returns it as constant. - * Otherwise, (when the polynomial is not constant polynomial) raises corresponding exception. - */ - public fun P.asConstant(): C = requireNotNull(asConstantOrNull()) { "Can not represent non-constant polynomial as a constant" } - /** * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is * zero, degree is -1. @@ -813,31 +687,6 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< @JvmName("constantPower") public override fun power(arg: C, exponent: UInt) : C = polynomialRing { power(arg, exponent) } - /** - * Check if the instant is zero constant. - */ - public override fun C.isZero(): Boolean = polynomialRing { this@isZero.isZero() } - /** - * Check if the instant is NOT zero constant. - */ - public override fun C.isNotZero(): Boolean = polynomialRing { this@isNotZero.isNotZero() } - /** - * Check if the instant is unit constant. - */ - public override fun C.isOne(): Boolean = polynomialRing { this@isOne.isOne() } - /** - * Check if the instant is NOT unit constant. - */ - public override fun C.isNotOne(): Boolean = polynomialRing { this@isNotOne.isNotOne() } - /** - * Check if the instant is minus unit constant. - */ - public override fun C.isMinusOne(): Boolean = polynomialRing { this@isMinusOne.isMinusOne() } - /** - * Check if the instant is NOT minus unit constant. - */ - public override fun C.isNotMinusOne(): Boolean = polynomialRing { this@isNotMinusOne.isNotMinusOne() } - /** * Instance of zero constant (zero of the underlying ring). */ @@ -907,31 +756,6 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< */ public override fun power(arg: P, exponent: UInt) : P = polynomialRing { power(arg, exponent) } - /** - * Check if the instant is zero polynomial. - */ - public override fun P.isZero(): Boolean = polynomialRing { this@isZero.isZero() } - /** - * Check if the instant is NOT zero polynomial. - */ - public override fun P.isNotZero(): Boolean = polynomialRing { this@isNotZero.isNotZero() } - /** - * Check if the instant is unit polynomial. - */ - public override fun P.isOne(): Boolean = polynomialRing { this@isOne.isOne() } - /** - * Check if the instant is NOT unit polynomial. - */ - public override fun P.isNotOne(): Boolean = polynomialRing { this@isNotOne.isNotOne() } - /** - * Check if the instant is minus unit polynomial. - */ - public override fun P.isMinusOne(): Boolean = polynomialRing { this@isMinusOne.isMinusOne() } - /** - * Check if the instant is NOT minus unit polynomial. - */ - public override fun P.isNotMinusOne(): Boolean = polynomialRing { this@isNotMinusOne.isNotMinusOne() } - /** * Instance of zero polynomial (zero of the polynomial ring). */ @@ -941,47 +765,11 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< */ public override val polynomialOne: P get() = polynomialRing.one - /** - * Checks equality of the polynomials. - */ - public override infix fun P.equalsTo(other: P): Boolean = polynomialRing { this@equalsTo equalsTo other } - /** - * Checks NOT equality of the polynomials. - */ - public override infix fun P.notEqualsTo(other: P): Boolean = polynomialRing { this@notEqualsTo notEqualsTo other } - /** * Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is * zero, degree is -1. */ public override val P.degree: Int get() = polynomialRing { this@degree.degree } - - /** - * Checks if the instant is constant polynomial (of degree no more than 0) over considered ring. - */ - public override fun P.isConstant(): Boolean = polynomialRing { this@isConstant.isConstant() } - /** - * Checks if the instant is **not** constant polynomial (of degree no more than 0) over considered ring. - */ - public override fun P.isNotConstant(): Boolean = polynomialRing { this@isNotConstant.isNotConstant() } - /** - * Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring. - */ - public override fun P.isNonZeroConstant(): Boolean = polynomialRing { this@isNonZeroConstant.isNonZeroConstant() } - /** - * Checks if the instant is **not** constant non-zero polynomial (of degree no more than 0) over considered ring. - */ - public override fun P.isNotNonZeroConstant(): Boolean = polynomialRing { this@isNotNonZeroConstant.isNotNonZeroConstant() } - /** - * If polynomial is a constant polynomial represents and returns it as constant. - * Otherwise, (when the polynomial is not constant polynomial) returns `null`. - */ - public override fun P.asConstantOrNull(): C? = polynomialRing { this@asConstantOrNull.asConstantOrNull() } - /** - * If polynomial is a constant polynomial represents and returns it as constant. - * Otherwise, (when the polynomial is not constant polynomial) raises corresponding exception. - */ - public override fun P.asConstant(): C = polynomialRing { this@asConstant.asConstant() } } /** @@ -1032,18 +820,11 @@ public abstract class PolynomialSpaceOfFractions< denominator ) - public override operator fun R.div(other: Int): R { - val otherAsConstant = constantNumber(other) - require(otherAsConstant.isNotZero()) { "/ by zero." } - return constructRationalFunction( + public override operator fun R.div(other: Int): R = + constructRationalFunction( numerator, - (denominator * other).also { - check(it.isNotZero()) { - "Got zero denominator during division of rational functions to constant. It means underlying ring of polynomials is not integral domain." - } - } + denominator * other ) - } /** * Returns sum of the integer represented as rational function and the rational function. @@ -1076,13 +857,11 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) - public override operator fun Int.div(other: R): R { - require(other.numerator.isNotZero()) { "/ by zero." } - return constructRationalFunction( + public override operator fun Int.div(other: R): R = + constructRationalFunction( this * other.denominator, other.numerator ) - } /** * Converts the integer [value] to rational function. @@ -1119,13 +898,11 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) - public override operator fun C.div(other: R): R { - require(other.numerator.isNotZero()) { "/ by zero." } - return constructRationalFunction( + public override operator fun C.div(other: R): R = + constructRationalFunction( this * other.denominator, other.numerator ) - } /** * Returns sum of the constant represented as rational function and the rational function. @@ -1152,17 +929,11 @@ public abstract class PolynomialSpaceOfFractions< denominator ) - public override operator fun R.div(other: C): R { - require(other.isNotZero()) { "/ by zero." } - return constructRationalFunction( + public override operator fun R.div(other: C): R = + constructRationalFunction( numerator, - (denominator * other).also { - check(it.isNotZero()) { - "Got zero denominator during division of rational functions to constant. It means underlying ring of polynomials is not integral domain." - } - } + denominator * other ) - } /** * Converts the constant [value] to rational function. @@ -1194,13 +965,11 @@ public abstract class PolynomialSpaceOfFractions< other.denominator ) - public override operator fun P.div(other: R): R { - require(other.numerator.isNotZero()) { "/ by zero." } - return constructRationalFunction( + public override operator fun P.div(other: R): R = + constructRationalFunction( this * other.denominator, other.numerator ) - } /** * Returns sum of the polynomial represented as rational function and the rational function. @@ -1227,17 +996,11 @@ public abstract class PolynomialSpaceOfFractions< denominator ) - public override operator fun R.div(other: P): R { - require(other.isNotZero()) { "/ by zero." } - return constructRationalFunction( + public override operator fun R.div(other: P): R = + constructRationalFunction( numerator, - (denominator * other).also { - require(it.isNotZero()) { - "Got zero denominator during division of rational functions to polynomial. It means underlying ring of polynomials is not integral domain." - } - } + denominator * other ) - } /** * Converts the polynomial [value] to rational function. @@ -1254,11 +1017,7 @@ public abstract class PolynomialSpaceOfFractions< public override operator fun R.plus(other: R): R = constructRationalFunction( numerator * other.denominator + denominator * other.numerator, - (denominator * other.denominator).also { - check(it.isNotZero()) { - "Got zero denominator during addition of rational functions. It means underlying ring of polynomials is not integral domain." - } - } + denominator * other.denominator ) /** * Returns difference of the rational functions. @@ -1266,11 +1025,7 @@ public abstract class PolynomialSpaceOfFractions< public override operator fun R.minus(other: R): R = constructRationalFunction( numerator * other.denominator - denominator * other.numerator, - (denominator * other.denominator).also { - check(it.isNotZero()) { - "Got zero denominator during subtraction of rational functions. It means underlying ring of polynomials is not integral domain." - } - } + denominator * other.denominator ) /** * Returns product of the rational functions. @@ -1278,24 +1033,14 @@ public abstract class PolynomialSpaceOfFractions< public override operator fun R.times(other: R): R = constructRationalFunction( numerator * other.numerator, - (denominator * other.denominator).also { - check(it.isNotZero()) { - "Got zero denominator during multiplication of rational functions. It means underlying ring of polynomials is not integral domain." - } - } + denominator * other.denominator ) - public override operator fun R.div(other: R): R { - require(other.isNotZero()) { "/ by zero." } - return constructRationalFunction( + public override operator fun R.div(other: R): R = + constructRationalFunction( numerator * other.denominator, - (denominator * other.numerator).also { - check(it.isNotZero()) { - "Got zero denominator during division of rational functions. It means underlying ring of polynomials is not integral domain." - } - } + denominator * other.numerator ) - } /** * Instance of zero rational function (zero of the rational functions ring). diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt index 35155d09d..50313cab9 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt @@ -121,9 +121,9 @@ public fun ListPolynomial.substitute(ring: Ring, arg: C): C = ring { public fun ListPolynomial.substitute(ring: Ring, arg: ListPolynomial) : ListPolynomial = ring { if (coefficients.isEmpty()) return ListPolynomial(emptyList()) - val thisDegree = coefficients.indexOfLast { it != zero } + val thisDegree = coefficients.lastIndex if (thisDegree == -1) return ListPolynomial(emptyList()) - val argDegree = arg.coefficients.indexOfLast { it != zero } + val argDegree = arg.coefficients.lastIndex if (argDegree == -1) return coefficients[0].asListPolynomial() val constantZero = zero val resultCoefs: MutableList = MutableList(thisDegree * argDegree + 1) { constantZero } @@ -144,7 +144,6 @@ public fun ListPolynomial.substitute(ring: Ring, arg: ListPolynomial(resultCoefs) } @@ -168,7 +167,6 @@ public fun ListPolynomial.derivative( ListPolynomial( buildList(max(0, coefficients.size - 1)) { for (deg in 1 .. coefficients.lastIndex) add(number(deg) * coefficients[deg]) - while (isNotEmpty() && elementAt(lastIndex) == algebra.zero) removeAt(lastIndex) } ) } @@ -186,7 +184,6 @@ public fun ListPolynomial.nthDerivative( buildList(max(0, coefficients.size - order)) { for (deg in order.. coefficients.lastIndex) add((deg - order + 1 .. deg).fold(coefficients[deg]) { acc, d -> acc * number(d) }) - while (isNotEmpty() && elementAt(lastIndex) == algebra.zero) removeAt(lastIndex) } ) } @@ -202,7 +199,6 @@ public fun ListPolynomial.antiderivative( buildList(coefficients.size + 1) { add(zero) coefficients.mapIndexedTo(this) { index, t -> t / number(index + 1) } - while (isNotEmpty() && elementAt(lastIndex) == algebra.zero) removeAt(lastIndex) } ) } @@ -220,7 +216,6 @@ public fun ListPolynomial.nthAntiderivative( buildList(coefficients.size + order) { repeat(order) { add(zero) } coefficients.mapIndexedTo(this) { index, c -> (1..order).fold(c) { acc, i -> acc / number(index + i) } } - while (isNotEmpty() && elementAt(lastIndex) == algebra.zero) removeAt(lastIndex) } ) } diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listRationalFunctionUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listRationalFunctionUtil.kt index 151c7bb8d..367212588 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listRationalFunctionUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listRationalFunctionUtil.kt @@ -55,11 +55,11 @@ public fun ListRationalFunction.substitute(ring: Field, arg: C): C = r internal fun ListPolynomial.substituteRationalFunctionTakeNumerator(ring: Ring, arg: ListRationalFunction): ListPolynomial = ring { if (coefficients.isEmpty()) return ListPolynomial(emptyList()) - val thisDegree = coefficients.indexOfLast { it != zero } + val thisDegree = coefficients.lastIndex if (thisDegree == -1) return ListPolynomial(emptyList()) val thisDegreeLog2 = 31 - thisDegree.countLeadingZeroBits() - val numeratorDegree = arg.numerator.coefficients.indexOfLast { it != zero } - val denominatorDegree = arg.denominator.coefficients.indexOfLast { it != zero } + val numeratorDegree = arg.numerator.coefficients.lastIndex + val denominatorDegree = arg.denominator.coefficients.lastIndex val argDegree = max(numeratorDegree, denominatorDegree) val constantZero = zero val powersOf2 = buildList(thisDegreeLog2 + 1) { diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt index 0d2c4b5fc..ac2647592 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialTest.kt @@ -9,7 +9,7 @@ import space.kscience.kmath.test.misc.* import kotlin.test.* -class ListPolynomialTest { +class ListPolynomialTest { // TODO: Adapt tests to changes @Test fun test_Polynomial_Int_plus() { RationalField.listPolynomial { @@ -489,94 +489,6 @@ class ListPolynomialTest { } } @Test - fun test_Polynomial_isZero() { - RationalField.listPolynomial { - assertTrue("test 1") { ListPolynomial().isZero() } - assertTrue("test 2") { ListPolynomial(Rational(0)).isZero() } - assertTrue("test 3") { ListPolynomial(Rational(0), Rational(0)).isZero() } - assertTrue("test 4") { ListPolynomial(Rational(0), Rational(0), Rational(0)) - .isZero() } - assertFalse("test 5") { ListPolynomial(Rational(3, 5)).isZero() } - assertFalse("test 6") { ListPolynomial(Rational(3, 5), Rational(0)) - .isZero() } - assertFalse("test 7") { ListPolynomial(Rational(0), Rational(3, 5), Rational(0)) - .isZero() } - } - } - @Test - fun test_Polynomial_isOne() { - RationalField.listPolynomial { - assertFalse("test 1") { ListPolynomial().isOne() } - assertFalse("test 2") { ListPolynomial(Rational(0)).isOne() } - assertFalse("test 3") { ListPolynomial(Rational(0), Rational(0)).isOne() } - assertFalse("test 4") { ListPolynomial(Rational(0), Rational(0), Rational(0)) - .isOne() } - assertFalse("test 5") { ListPolynomial(Rational(3, 5)).isOne() } - assertTrue("test 6") { ListPolynomial(Rational(5, 5)).isOne() } - assertFalse("test 7") { ListPolynomial(Rational(3, 5), Rational(0)).isOne() } - assertTrue("test 8") { ListPolynomial(Rational(3, 3), Rational(0)).isOne() } - assertFalse("test 9") { ListPolynomial(Rational(0), Rational(3, 5), Rational(0)) - .isOne() } - assertFalse("test 10") { ListPolynomial(Rational(0), Rational(5, 5), Rational(0)) - .isOne() } - assertFalse("test 11") { ListPolynomial(Rational(1), Rational(3, 5), Rational(0)) - .isOne() } - assertFalse("test 12") { ListPolynomial(Rational(1), Rational(5, 5), Rational(0)) - .isOne() } - } - } - @Test - fun test_Polynomial_isMinusOne() { - RationalField.listPolynomial { - assertFalse("test 1") { ListPolynomial().isMinusOne() } - assertFalse("test 2") { ListPolynomial(Rational(0)).isMinusOne() } - assertFalse("test 3") { ListPolynomial(Rational(0), Rational(0)).isMinusOne() } - assertFalse("test 4") { ListPolynomial(Rational(0), Rational(0), Rational(0)) - .isMinusOne() } - assertFalse("test 5") { ListPolynomial(Rational(3, 5)).isMinusOne() } - assertTrue("test 6") { ListPolynomial(Rational(-5, 5)).isMinusOne() } - assertFalse("test 7") { ListPolynomial(Rational(3, 5), Rational(0)).isMinusOne() } - assertTrue("test 8") { ListPolynomial(Rational(-3, 3), Rational(0)).isMinusOne() } - assertFalse("test 9") { ListPolynomial(Rational(0), Rational(3, 5), Rational(0)) - .isMinusOne() } - assertFalse("test 10") { ListPolynomial(Rational(0), Rational(5, -5), Rational(0)) - .isMinusOne() } - assertFalse("test 11") { ListPolynomial(Rational(-1), Rational(3, 5), Rational(0)) - .isMinusOne() } - assertFalse("test 12") { ListPolynomial(Rational(-1), Rational(5, -5), Rational(0)) - .isMinusOne() } - } - } - @Test - fun test_Polynomial_Polynomial_equalsTo() { - RationalField.listPolynomial { - assertTrue("test 1") { - ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) equalsTo - ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - } - assertTrue("test 2") { - ListPolynomial(Rational(5, 9), Rational(0), Rational(-8, 7)) equalsTo - ListPolynomial(Rational(5, 9), Rational(0), Rational(-8, 7)) - } - assertTrue("test 3") { - ListPolynomial(Rational(0), Rational(0), Rational(-8, 7), Rational(0), Rational(0)) equalsTo - ListPolynomial(Rational(0), Rational(0), Rational(-8, 7)) - } - assertFalse("test 4") { - ListPolynomial(Rational(5, 9), Rational(5, 7), Rational(-8, 7)) equalsTo - ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - } - assertFalse("test 5") { - ListPolynomial(Rational(8, 3), Rational(0), Rational(-8, 7)) equalsTo - ListPolynomial(Rational(5, 9), Rational(0), Rational(-8, 7)) - } - assertFalse("test 6") { - ListPolynomial(Rational(0), Rational(0), Rational(-8, 7), Rational(0), Rational(0)) equalsTo - ListPolynomial(Rational(0), Rational(0), Rational(8, 7)) - } - } - } - @Test fun test_Polynomial_degree() { RationalField.listPolynomial { assertEquals( @@ -636,70 +548,4 @@ class ListPolynomialTest { ) } } - @Test - fun test_Polynomial_asConstantOrNull() { - RationalField.listPolynomial { - assertEquals( - Rational(0), - ListPolynomial().asConstantOrNull(), - "test 1" - ) - assertEquals( - Rational(0), - ListPolynomial(Rational(0)).asConstantOrNull(), - "test 2" - ) - assertEquals( - Rational(0), - ListPolynomial(Rational(0), Rational(0)).asConstantOrNull(), - "test 3" - ) - assertEquals( - Rational(0), - ListPolynomial(Rational(0), Rational(0), Rational(0)).asConstantOrNull(), - "test 4" - ) - assertEquals( - Rational(-7, 9), - ListPolynomial(Rational(-7, 9)).asConstantOrNull(), - "test 5" - ) - assertEquals( - Rational(-7, 9), - ListPolynomial(Rational(-7, 9), Rational(0)).asConstantOrNull(), - "test 6" - ) - assertEquals( - Rational(-7, 9), - ListPolynomial(Rational(-7, 9), Rational(0), Rational(0)).asConstantOrNull(), - "test 7" - ) - assertEquals( - null, - ListPolynomial(Rational(0), Rational(-7, 9)).asConstantOrNull(), - "test 8" - ) - assertEquals( - null, - ListPolynomial(Rational(0), Rational(-7, 9), Rational(0)).asConstantOrNull(), - "test 9" - ) - assertEquals( - null, - ListPolynomial(Rational(0), Rational(0), Rational(-7, 9)).asConstantOrNull(), - "test 10" - ) - assertEquals( - null, - ListPolynomial(Rational(4, 15), Rational(0), Rational(-7, 9)).asConstantOrNull(), - "test 11" - ) - assertEquals( - null, - ListPolynomial(Rational(4, 15), Rational(0), Rational(-7, 9), Rational(0)) - .asConstantOrNull(), - "test 12" - ) - } - } } \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt index 50ae18260..c4f07d957 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/functions/ListPolynomialUtilTest.kt @@ -12,7 +12,7 @@ import kotlin.test.assertEquals import kotlin.test.assertFailsWith -class ListPolynomialUtilTest { +class ListPolynomialUtilTest { // TODO: Adapt tests to changes @Test fun test_substitute_Double() { assertEquals(