forked from kscience/kmath
1. Prototyped Rational Functions
2. Added abstract interfaces for removing boilerplates 3. Changed or added default values in interfaces 4. Renamed non-operator `equals` to `equalsTo`, and made it infix
This commit is contained in:
parent
033edd3feb
commit
de53d032af
@ -154,7 +154,7 @@ public interface AbstractPolynomialSpace<C, P: AbstractPolynomial<C>> : Ring<P>
|
|||||||
* Check if the instant is NOT zero constant.
|
* Check if the instant is NOT zero constant.
|
||||||
*/
|
*/
|
||||||
@JvmName("constantIsNotZero")
|
@JvmName("constantIsNotZero")
|
||||||
public fun C.isNotZero(): Boolean
|
public fun C.isNotZero(): Boolean = !isZero()
|
||||||
/**
|
/**
|
||||||
* Check if the instant is unit constant.
|
* Check if the instant is unit constant.
|
||||||
*/
|
*/
|
||||||
@ -164,7 +164,7 @@ public interface AbstractPolynomialSpace<C, P: AbstractPolynomial<C>> : Ring<P>
|
|||||||
* Check if the instant is NOT unit constant.
|
* Check if the instant is NOT unit constant.
|
||||||
*/
|
*/
|
||||||
@JvmName("constantIsNotOne")
|
@JvmName("constantIsNotOne")
|
||||||
public fun C.isNotOne(): Boolean
|
public fun C.isNotOne(): Boolean = !isOne()
|
||||||
/**
|
/**
|
||||||
* Check if the instant is minus unit constant.
|
* Check if the instant is minus unit constant.
|
||||||
*/
|
*/
|
||||||
@ -174,7 +174,7 @@ public interface AbstractPolynomialSpace<C, P: AbstractPolynomial<C>> : Ring<P>
|
|||||||
* Check if the instant is NOT minus unit constant.
|
* Check if the instant is NOT minus unit constant.
|
||||||
*/
|
*/
|
||||||
@JvmName("constantIsNotMinusOne")
|
@JvmName("constantIsNotMinusOne")
|
||||||
public fun C.isNotMinusOne(): Boolean
|
public fun C.isNotMinusOne(): Boolean = !isMinusOne()
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Constant-polynomial relation
|
// region Constant-polynomial relation
|
||||||
@ -232,27 +232,27 @@ public interface AbstractPolynomialSpace<C, P: AbstractPolynomial<C>> : Ring<P>
|
|||||||
/**
|
/**
|
||||||
* Check if the instant is zero polynomial.
|
* Check if the instant is zero polynomial.
|
||||||
*/
|
*/
|
||||||
public fun P.isZero(): Boolean = this == zero
|
public fun P.isZero(): Boolean = this equalsTo zero
|
||||||
/**
|
/**
|
||||||
* Check if the instant is NOT zero polynomial.
|
* Check if the instant is NOT zero polynomial.
|
||||||
*/
|
*/
|
||||||
public fun P.isNotZero(): Boolean = this != zero
|
public fun P.isNotZero(): Boolean = !isZero()
|
||||||
/**
|
/**
|
||||||
* Check if the instant is unit polynomial.
|
* Check if the instant is unit polynomial.
|
||||||
*/
|
*/
|
||||||
public fun P.isOne(): Boolean = this == one
|
public fun P.isOne(): Boolean = this equalsTo one
|
||||||
/**
|
/**
|
||||||
* Check if the instant is NOT unit polynomial.
|
* Check if the instant is NOT unit polynomial.
|
||||||
*/
|
*/
|
||||||
public fun P.isNotOne(): Boolean = this != one
|
public fun P.isNotOne(): Boolean = !isOne()
|
||||||
/**
|
/**
|
||||||
* Check if the instant is minus unit polynomial.
|
* Check if the instant is minus unit polynomial.
|
||||||
*/
|
*/
|
||||||
public fun P.isMinusOne(): Boolean = this == -one
|
public fun P.isMinusOne(): Boolean = this equalsTo -one
|
||||||
/**
|
/**
|
||||||
* Check if the instant is NOT minus unit polynomial.
|
* Check if the instant is NOT minus unit polynomial.
|
||||||
*/
|
*/
|
||||||
public fun P.isNotMinusOne(): Boolean = this != -one
|
public fun P.isNotMinusOne(): Boolean = !isMinusOne()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instance of zero polynomial (zero of the polynomial ring).
|
* Instance of zero polynomial (zero of the polynomial ring).
|
||||||
@ -266,8 +266,11 @@ public interface AbstractPolynomialSpace<C, P: AbstractPolynomial<C>> : Ring<P>
|
|||||||
/**
|
/**
|
||||||
* Checks equality of the polynomials.
|
* Checks equality of the polynomials.
|
||||||
*/
|
*/
|
||||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals")
|
public infix fun P.equalsTo(other: P): Boolean
|
||||||
public fun P.equals(other: P): Boolean
|
/**
|
||||||
|
* Checks NOT equality of the polynomials.
|
||||||
|
*/
|
||||||
|
public infix fun P.notEqualsTo(other: P): Boolean = !(this equalsTo other)
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// Not sure is it necessary...
|
// Not sure is it necessary...
|
||||||
@ -311,3 +314,106 @@ public interface AbstractPolynomialSpace<C, P: AbstractPolynomial<C>> : Ring<P>
|
|||||||
override fun multiply(left: P, right: P): P = left * right
|
override fun multiply(left: P, right: P): P = left * right
|
||||||
// endregion
|
// endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstraction of ring of polynomials of type [P] over ring of constants of type [C].
|
||||||
|
*
|
||||||
|
* @param C the type of constants. Polynomials have them as a coefficients in their terms.
|
||||||
|
* @param P the type of polynomials.
|
||||||
|
*/
|
||||||
|
@Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE")
|
||||||
|
public interface AbstractPolynomialSpaceOverRing<C, P: AbstractPolynomial<C>, A: Ring<C>> : AbstractPolynomialSpace<C, P> {
|
||||||
|
|
||||||
|
public val ring: A
|
||||||
|
|
||||||
|
// region Constant-integer relation
|
||||||
|
/**
|
||||||
|
* Returns sum of the constant and the integer represented as constant (member of underlying ring).
|
||||||
|
*
|
||||||
|
* The operation is equivalent to adding [other] copies of unit of underlying ring to [this].
|
||||||
|
*/
|
||||||
|
@JvmName("constantIntPlus")
|
||||||
|
public override operator fun C.plus(other: Int): C = ring { optimizedAddMultiplied(this@plus, one, other) }
|
||||||
|
/**
|
||||||
|
* Returns difference between the constant and the integer represented as constant (member of underlying ring).
|
||||||
|
*
|
||||||
|
* The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this].
|
||||||
|
*/
|
||||||
|
@JvmName("constantIntMinus")
|
||||||
|
public override operator fun C.minus(other: Int): C = ring { optimizedAddMultiplied(this@minus, one, -other) }
|
||||||
|
/**
|
||||||
|
* Returns product of the constant and the integer represented as constant (member of underlying ring).
|
||||||
|
*
|
||||||
|
* The operation is equivalent to sum of [other] copies of [this].
|
||||||
|
*/
|
||||||
|
@JvmName("constantIntTimes")
|
||||||
|
public override operator fun C.times(other: Int): C = ring { optimizedMultiply(this@times, other) }
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Integer-constant relation
|
||||||
|
/**
|
||||||
|
* Returns sum of the integer represented as constant (member of underlying ring) and the constant.
|
||||||
|
*
|
||||||
|
* The operation is equivalent to adding [this] copies of unit of underlying ring to [other].
|
||||||
|
*/
|
||||||
|
@JvmName("intConstantPlus")
|
||||||
|
public override operator fun Int.plus(other: C): C = ring { optimizedAddMultiplied(other, one, this@plus) }
|
||||||
|
/**
|
||||||
|
* Returns difference between the integer represented as constant (member of underlying ring) and the constant.
|
||||||
|
*
|
||||||
|
* The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other].
|
||||||
|
*/
|
||||||
|
@JvmName("intConstantMinus")
|
||||||
|
public override operator fun Int.minus(other: C): C = ring { optimizedAddMultiplied(-other, one, this@minus) }
|
||||||
|
/**
|
||||||
|
* Returns product of the integer represented as constant (member of underlying ring) and the constant.
|
||||||
|
*
|
||||||
|
* The operation is equivalent to sum of [this] copies of [other].
|
||||||
|
*/
|
||||||
|
@JvmName("intConstantTimes")
|
||||||
|
public override operator fun Int.times(other: C): C = ring { optimizedMultiply(other, this@times) }
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Constant-constant relation
|
||||||
|
/**
|
||||||
|
* Returns negation of the constant.
|
||||||
|
*/
|
||||||
|
@JvmName("constantUnaryMinus")
|
||||||
|
@JsName("constantUnaryMinus")
|
||||||
|
public override operator fun C.unaryMinus(): C = ring { -this@unaryMinus }
|
||||||
|
/**
|
||||||
|
* Returns sum of the constants.
|
||||||
|
*/
|
||||||
|
@JvmName("constantPlus")
|
||||||
|
@JsName("constantPlus")
|
||||||
|
public override operator fun C.plus(other: C): C = ring { this@plus + other }
|
||||||
|
/**
|
||||||
|
* Returns difference of the constants.
|
||||||
|
*/
|
||||||
|
@JvmName("constantMinus")
|
||||||
|
@JsName("constantMinus")
|
||||||
|
public override operator fun C.minus(other: C): C = ring { this@minus - other }
|
||||||
|
/**
|
||||||
|
* Returns product of the constants.
|
||||||
|
*/
|
||||||
|
@JvmName("constantTimes")
|
||||||
|
@JsName("constantTimes")
|
||||||
|
public override operator fun C.times(other: C): C = ring { this@times * other }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the instant is zero constant.
|
||||||
|
*/
|
||||||
|
@JvmName("constantIsZero")
|
||||||
|
public override fun C.isZero(): Boolean = ring { this == zero }
|
||||||
|
/**
|
||||||
|
* Check if the instant is unit constant.
|
||||||
|
*/
|
||||||
|
@JvmName("constantIsOne")
|
||||||
|
public override fun C.isOne(): Boolean = ring { this == one }
|
||||||
|
/**
|
||||||
|
* Check if the instant is minus unit constant.
|
||||||
|
*/
|
||||||
|
@JvmName("constantIsMinusOne")
|
||||||
|
public override fun C.isMinusOne(): Boolean = ring { this == -one }
|
||||||
|
// endregion
|
||||||
|
}
|
@ -13,7 +13,12 @@ import kotlin.jvm.JvmName
|
|||||||
/**
|
/**
|
||||||
* Abstraction of rational function.
|
* Abstraction of rational function.
|
||||||
*/
|
*/
|
||||||
public interface AbstractRationalFunction<C, P: AbstractPolynomial<C>>
|
public interface AbstractRationalFunction<C, P: AbstractPolynomial<C>> {
|
||||||
|
public val numerator: P
|
||||||
|
public val denominator: P
|
||||||
|
public operator fun component1(): P = numerator
|
||||||
|
public operator fun component2(): P = denominator
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE")
|
@Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE")
|
||||||
public interface AbstractRationalFunctionalSpace<C, P: AbstractPolynomial<C>, R: AbstractRationalFunction<C, P>> : Ring<R> {
|
public interface AbstractRationalFunctionalSpace<C, P: AbstractPolynomial<C>, R: AbstractRationalFunction<C, P>> : Ring<R> {
|
||||||
@ -190,7 +195,7 @@ public interface AbstractRationalFunctionalSpace<C, P: AbstractPolynomial<C>, R:
|
|||||||
* Check if the instant is NOT zero constant.
|
* Check if the instant is NOT zero constant.
|
||||||
*/
|
*/
|
||||||
@JvmName("constantIsNotZero")
|
@JvmName("constantIsNotZero")
|
||||||
public fun C.isNotZero(): Boolean
|
public fun C.isNotZero(): Boolean = !isZero()
|
||||||
/**
|
/**
|
||||||
* Check if the instant is unit constant.
|
* Check if the instant is unit constant.
|
||||||
*/
|
*/
|
||||||
@ -200,7 +205,7 @@ public interface AbstractRationalFunctionalSpace<C, P: AbstractPolynomial<C>, R:
|
|||||||
* Check if the instant is NOT unit constant.
|
* Check if the instant is NOT unit constant.
|
||||||
*/
|
*/
|
||||||
@JvmName("constantIsNotOne")
|
@JvmName("constantIsNotOne")
|
||||||
public fun C.isNotOne(): Boolean
|
public fun C.isNotOne(): Boolean = !isOne()
|
||||||
/**
|
/**
|
||||||
* Check if the instant is minus unit constant.
|
* Check if the instant is minus unit constant.
|
||||||
*/
|
*/
|
||||||
@ -210,7 +215,7 @@ public interface AbstractRationalFunctionalSpace<C, P: AbstractPolynomial<C>, R:
|
|||||||
* Check if the instant is NOT minus unit constant.
|
* Check if the instant is NOT minus unit constant.
|
||||||
*/
|
*/
|
||||||
@JvmName("constantIsNotMinusOne")
|
@JvmName("constantIsNotMinusOne")
|
||||||
public fun C.isNotMinusOne(): Boolean
|
public fun C.isNotMinusOne(): Boolean = !isMinusOne()
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Constant-polynomial relation
|
// region Constant-polynomial relation
|
||||||
@ -268,42 +273,45 @@ public interface AbstractRationalFunctionalSpace<C, P: AbstractPolynomial<C>, R:
|
|||||||
/**
|
/**
|
||||||
* Check if the instant is zero polynomial.
|
* Check if the instant is zero polynomial.
|
||||||
*/
|
*/
|
||||||
public fun P.isZero(): Boolean = this == zeroPolynomial
|
public fun P.isZero(): Boolean = this equalsTo polynomialZero
|
||||||
/**
|
/**
|
||||||
* Check if the instant is NOT zero polynomial.
|
* Check if the instant is NOT zero polynomial.
|
||||||
*/
|
*/
|
||||||
public fun P.isNotZero(): Boolean = this != zeroPolynomial
|
public fun P.isNotZero(): Boolean = !isZero()
|
||||||
/**
|
/**
|
||||||
* Check if the instant is unit polynomial.
|
* Check if the instant is unit polynomial.
|
||||||
*/
|
*/
|
||||||
public fun P.isOne(): Boolean = this == onePolynomial
|
public fun P.isOne(): Boolean = this equalsTo polynomialOne
|
||||||
/**
|
/**
|
||||||
* Check if the instant is NOT unit polynomial.
|
* Check if the instant is NOT unit polynomial.
|
||||||
*/
|
*/
|
||||||
public fun P.isNotOne(): Boolean = this != onePolynomial
|
public fun P.isNotOne(): Boolean = !isOne()
|
||||||
/**
|
/**
|
||||||
* Check if the instant is minus unit polynomial.
|
* Check if the instant is minus unit polynomial.
|
||||||
*/
|
*/
|
||||||
public fun P.isMinusOne(): Boolean = this == -onePolynomial
|
public fun P.isMinusOne(): Boolean = this equalsTo -polynomialOne
|
||||||
/**
|
/**
|
||||||
* Check if the instant is NOT minus unit polynomial.
|
* Check if the instant is NOT minus unit polynomial.
|
||||||
*/
|
*/
|
||||||
public fun P.isNotMinusOne(): Boolean = this != -onePolynomial
|
public fun P.isNotMinusOne(): Boolean = !isMinusOne()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instance of zero polynomial (zero of the polynomial ring).
|
* Instance of zero polynomial (zero of the polynomial ring).
|
||||||
*/
|
*/
|
||||||
public val zeroPolynomial: P
|
public val polynomialZero: P
|
||||||
/**
|
/**
|
||||||
* Instance of unit polynomial (unit of the polynomial ring).
|
* Instance of unit polynomial (unit of the polynomial ring).
|
||||||
*/
|
*/
|
||||||
public val onePolynomial: P
|
public val polynomialOne: P
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks equality of the polynomials.
|
* Checks equality of the polynomials.
|
||||||
*/
|
*/
|
||||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals")
|
public infix fun P.equalsTo(other: P): Boolean
|
||||||
public fun P.equals(other: P): Boolean
|
/**
|
||||||
|
* Checks NOT equality of the polynomials.
|
||||||
|
*/
|
||||||
|
public infix fun P.notEqualsTo(other: P): Boolean = !(this equalsTo other)
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Constant-rational relation
|
// region Constant-rational relation
|
||||||
@ -391,27 +399,27 @@ public interface AbstractRationalFunctionalSpace<C, P: AbstractPolynomial<C>, R:
|
|||||||
/**
|
/**
|
||||||
* Check if the instant is zero rational function.
|
* Check if the instant is zero rational function.
|
||||||
*/
|
*/
|
||||||
public fun R.isZero(): Boolean = this == zero
|
public fun R.isZero(): Boolean = this equalsTo zero
|
||||||
/**
|
/**
|
||||||
* Check if the instant is NOT zero rational function.
|
* Check if the instant is NOT zero rational function.
|
||||||
*/
|
*/
|
||||||
public fun R.isNotZero(): Boolean = this != zero
|
public fun R.isNotZero(): Boolean = !isZero()
|
||||||
/**
|
/**
|
||||||
* Check if the instant is unit rational function.
|
* Check if the instant is unit rational function.
|
||||||
*/
|
*/
|
||||||
public fun R.isOne(): Boolean = this == one
|
public fun R.isOne(): Boolean = this equalsTo one
|
||||||
/**
|
/**
|
||||||
* Check if the instant is NOT unit rational function.
|
* Check if the instant is NOT unit rational function.
|
||||||
*/
|
*/
|
||||||
public fun R.isNotOne(): Boolean = this != one
|
public fun R.isNotOne(): Boolean = !isOne()
|
||||||
/**
|
/**
|
||||||
* Check if the instant is minus unit rational function.
|
* Check if the instant is minus unit rational function.
|
||||||
*/
|
*/
|
||||||
public fun R.isMinusOne(): Boolean = this == -one
|
public fun R.isMinusOne(): Boolean = this equalsTo -one
|
||||||
/**
|
/**
|
||||||
* Check if the instant is NOT minus unit rational function.
|
* Check if the instant is NOT minus unit rational function.
|
||||||
*/
|
*/
|
||||||
public fun R.isNotMinusOne(): Boolean = this != -one
|
public fun R.isNotMinusOne(): Boolean = !isMinusOne()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instance of zero rational function (zero of the rational functions ring).
|
* Instance of zero rational function (zero of the rational functions ring).
|
||||||
@ -425,8 +433,11 @@ public interface AbstractRationalFunctionalSpace<C, P: AbstractPolynomial<C>, R:
|
|||||||
/**
|
/**
|
||||||
* Checks equality of the rational functions.
|
* Checks equality of the rational functions.
|
||||||
*/
|
*/
|
||||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals")
|
public infix fun R.equalsTo(other: R): Boolean
|
||||||
public fun R.equals(other: R): Boolean
|
/**
|
||||||
|
* Checks NOT equality of the polynomials.
|
||||||
|
*/
|
||||||
|
public infix fun R.notEqualsTo(other: R): Boolean = !(this equalsTo other)
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// Not sure is it necessary...
|
// Not sure is it necessary...
|
||||||
@ -453,35 +464,31 @@ public interface AbstractRationalFunctionalSpace<C, P: AbstractPolynomial<C>, R:
|
|||||||
* Checks if the instant is **not** constant non-zero polynomial (of degree no more than 0) over considered ring.
|
* 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()
|
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?
|
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 = asConstantOrNull() ?: error("Can not represent non-constant polynomial as a constant")
|
public fun P.asConstant(): C = asConstantOrNull() ?: error("Can not represent non-constant polynomial as a constant")
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// Not sure is it necessary...
|
// Not sure is it necessary...
|
||||||
// region Polynomial properties
|
// region Rational properties
|
||||||
/**
|
/**
|
||||||
* Checks if the instant is constant polynomial (of degree no more than 0) over considered ring.
|
* Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is
|
||||||
|
* zero, degree is -1.
|
||||||
*/
|
*/
|
||||||
public fun R.isConstant(): Boolean
|
public val R.numeratorDegree: Int get() = numerator.degree
|
||||||
/**
|
/**
|
||||||
* Checks if the instant is **not** constant polynomial (of degree no more than 0) over considered ring.
|
* Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is
|
||||||
|
* zero, degree is -1.
|
||||||
*/
|
*/
|
||||||
public fun R.isNotConstant(): Boolean = !isConstant()
|
public val R.denominatorDegree: Int get() = denominator.degree
|
||||||
/**
|
|
||||||
* Checks if the instant is constant non-zero polynomial (of degree no more than 0) over considered ring.
|
|
||||||
*/
|
|
||||||
public fun R.isNonZeroConstant(): Boolean
|
|
||||||
/**
|
|
||||||
* Checks if the instant is **not** constant non-zero polynomial (of degree no more than 0) over considered ring.
|
|
||||||
*/
|
|
||||||
public fun R.isNotNonZeroConstant(): Boolean = !isNonZeroConstant()
|
|
||||||
|
|
||||||
public fun R.asConstantOrNull(): C?
|
|
||||||
|
|
||||||
public fun R.asConstant(): C = asConstantOrNull() ?: error("Can not represent non-constant polynomial as a constant")
|
|
||||||
|
|
||||||
// TODO: Перенести в реализацию
|
// TODO: Перенести в реализацию
|
||||||
// fun R.substitute(argument: C): C
|
// fun R.substitute(argument: C): C
|
||||||
@ -503,3 +510,414 @@ public interface AbstractRationalFunctionalSpace<C, P: AbstractPolynomial<C>, R:
|
|||||||
override fun multiply(left: R, right: R): R = left * right
|
override fun multiply(left: R, right: R): R = left * right
|
||||||
// endregion
|
// endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE")
|
||||||
|
public interface AbstractRationalFunctionalSpaceOverRing<C, P: AbstractPolynomial<C>, R: AbstractRationalFunction<C, P>, A: Ring<C>> : AbstractRationalFunctionalSpace<C, P, R> {
|
||||||
|
|
||||||
|
public val ring: A
|
||||||
|
|
||||||
|
// region Constant-integer relation
|
||||||
|
/**
|
||||||
|
* Returns sum of the constant and the integer represented as constant (member of underlying ring).
|
||||||
|
*
|
||||||
|
* The operation is equivalent to adding [other] copies of unit of underlying ring to [this].
|
||||||
|
*/
|
||||||
|
@JvmName("constantIntPlus")
|
||||||
|
public override operator fun C.plus(other: Int): C = ring { optimizedAddMultiplied(this@plus, one, other) }
|
||||||
|
/**
|
||||||
|
* Returns difference between the constant and the integer represented as constant (member of underlying ring).
|
||||||
|
*
|
||||||
|
* The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this].
|
||||||
|
*/
|
||||||
|
@JvmName("constantIntMinus")
|
||||||
|
public override operator fun C.minus(other: Int): C = ring { optimizedAddMultiplied(this@minus, one, -other) }
|
||||||
|
/**
|
||||||
|
* Returns product of the constant and the integer represented as constant (member of underlying ring).
|
||||||
|
*
|
||||||
|
* The operation is equivalent to sum of [other] copies of [this].
|
||||||
|
*/
|
||||||
|
@JvmName("constantIntTimes")
|
||||||
|
public override operator fun C.times(other: Int): C = ring { optimizedMultiply(this@times, other) }
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Integer-constant relation
|
||||||
|
/**
|
||||||
|
* Returns sum of the integer represented as constant (member of underlying ring) and the constant.
|
||||||
|
*
|
||||||
|
* The operation is equivalent to adding [this] copies of unit of underlying ring to [other].
|
||||||
|
*/
|
||||||
|
@JvmName("intConstantPlus")
|
||||||
|
public override operator fun Int.plus(other: C): C = ring { optimizedAddMultiplied(other, one, this@plus) }
|
||||||
|
/**
|
||||||
|
* Returns difference between the integer represented as constant (member of underlying ring) and the constant.
|
||||||
|
*
|
||||||
|
* The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other].
|
||||||
|
*/
|
||||||
|
@JvmName("intConstantMinus")
|
||||||
|
public override operator fun Int.minus(other: C): C = ring { optimizedAddMultiplied(-other, one, this@minus) }
|
||||||
|
/**
|
||||||
|
* Returns product of the integer represented as constant (member of underlying ring) and the constant.
|
||||||
|
*
|
||||||
|
* The operation is equivalent to sum of [this] copies of [other].
|
||||||
|
*/
|
||||||
|
@JvmName("intConstantTimes")
|
||||||
|
public override operator fun Int.times(other: C): C = ring { optimizedMultiply(other, this@times) }
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Constant-constant relation
|
||||||
|
/**
|
||||||
|
* Returns the same constant.
|
||||||
|
*/
|
||||||
|
@JvmName("constantUnaryPlus")
|
||||||
|
@JsName("constantUnaryPlus")
|
||||||
|
public override operator fun C.unaryPlus(): C = ring { +this@unaryPlus }
|
||||||
|
/**
|
||||||
|
* Returns negation of the constant.
|
||||||
|
*/
|
||||||
|
@JvmName("constantUnaryMinus")
|
||||||
|
@JsName("constantUnaryMinus")
|
||||||
|
public override operator fun C.unaryMinus(): C = ring { -this@unaryMinus }
|
||||||
|
/**
|
||||||
|
* Returns sum of the constants.
|
||||||
|
*/
|
||||||
|
@JvmName("constantPlus")
|
||||||
|
@JsName("constantPlus")
|
||||||
|
public override operator fun C.plus(other: C): C = ring { this@plus + other }
|
||||||
|
/**
|
||||||
|
* Returns difference of the constants.
|
||||||
|
*/
|
||||||
|
@JvmName("constantMinus")
|
||||||
|
@JsName("constantMinus")
|
||||||
|
public override operator fun C.minus(other: C): C = ring { this@minus - other }
|
||||||
|
/**
|
||||||
|
* Returns product of the constants.
|
||||||
|
*/
|
||||||
|
@JvmName("constantTimes")
|
||||||
|
@JsName("constantTimes")
|
||||||
|
public override operator fun C.times(other: C): C = ring { this@times * other }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the instant is zero constant.
|
||||||
|
*/
|
||||||
|
@JvmName("constantIsZero")
|
||||||
|
public override fun C.isZero(): Boolean = ring { this@isZero.isZero() }
|
||||||
|
/**
|
||||||
|
* Check if the instant is NOT zero constant.
|
||||||
|
*/
|
||||||
|
@JvmName("constantIsNotZero")
|
||||||
|
public override fun C.isNotZero(): Boolean = ring { this@isNotZero.isNotZero() }
|
||||||
|
/**
|
||||||
|
* Check if the instant is unit constant.
|
||||||
|
*/
|
||||||
|
@JvmName("constantIsOne")
|
||||||
|
public override fun C.isOne(): Boolean = ring { this@isOne.isOne() }
|
||||||
|
/**
|
||||||
|
* Check if the instant is NOT unit constant.
|
||||||
|
*/
|
||||||
|
@JvmName("constantIsNotOne")
|
||||||
|
public override fun C.isNotOne(): Boolean = ring { this@isNotOne.isNotOne() }
|
||||||
|
/**
|
||||||
|
* Check if the instant is minus unit constant.
|
||||||
|
*/
|
||||||
|
@JvmName("constantIsMinusOne")
|
||||||
|
public override fun C.isMinusOne(): Boolean = ring { this@isMinusOne.isMinusOne() }
|
||||||
|
/**
|
||||||
|
* Check if the instant is NOT minus unit constant.
|
||||||
|
*/
|
||||||
|
@JvmName("constantIsNotMinusOne")
|
||||||
|
public override fun C.isNotMinusOne(): Boolean = ring { this@isNotMinusOne.isNotMinusOne() }
|
||||||
|
// endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE")
|
||||||
|
public interface AbstractRationalFunctionalSpaceOverPolynomialSpace<C, P: AbstractPolynomial<C>, R: AbstractRationalFunction<C, P>, A: Ring<C>> : AbstractRationalFunctionalSpace<C, P, R> {
|
||||||
|
|
||||||
|
public val polynomialRing: AbstractPolynomialSpace<C, P>
|
||||||
|
|
||||||
|
// region Constant-integer relation
|
||||||
|
/**
|
||||||
|
* Returns sum of the constant and the integer represented as constant (member of underlying ring).
|
||||||
|
*
|
||||||
|
* The operation is equivalent to adding [other] copies of unit of underlying ring to [this].
|
||||||
|
*/
|
||||||
|
@JvmName("constantIntPlus")
|
||||||
|
public override operator fun C.plus(other: Int): C = polynomialRing { this@plus + other }
|
||||||
|
/**
|
||||||
|
* Returns difference between the constant and the integer represented as constant (member of underlying ring).
|
||||||
|
*
|
||||||
|
* The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this].
|
||||||
|
*/
|
||||||
|
@JvmName("constantIntMinus")
|
||||||
|
public override operator fun C.minus(other: Int): C = polynomialRing { this@minus - other }
|
||||||
|
/**
|
||||||
|
* Returns product of the constant and the integer represented as constant (member of underlying ring).
|
||||||
|
*
|
||||||
|
* The operation is equivalent to sum of [other] copies of [this].
|
||||||
|
*/
|
||||||
|
@JvmName("constantIntTimes")
|
||||||
|
public override operator fun C.times(other: Int): C = polynomialRing { this@times * other }
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Integer-constant relation
|
||||||
|
/**
|
||||||
|
* Returns sum of the integer represented as constant (member of underlying ring) and the constant.
|
||||||
|
*
|
||||||
|
* The operation is equivalent to adding [this] copies of unit of underlying ring to [other].
|
||||||
|
*/
|
||||||
|
@JvmName("intConstantPlus")
|
||||||
|
public override operator fun Int.plus(other: C): C = polynomialRing { this@plus + other }
|
||||||
|
/**
|
||||||
|
* Returns difference between the integer represented as constant (member of underlying ring) and the constant.
|
||||||
|
*
|
||||||
|
* The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other].
|
||||||
|
*/
|
||||||
|
@JvmName("intConstantMinus")
|
||||||
|
public override operator fun Int.minus(other: C): C = polynomialRing { this@minus - other }
|
||||||
|
/**
|
||||||
|
* Returns product of the integer represented as constant (member of underlying ring) and the constant.
|
||||||
|
*
|
||||||
|
* The operation is equivalent to sum of [this] copies of [other].
|
||||||
|
*/
|
||||||
|
@JvmName("intConstantTimes")
|
||||||
|
public override operator fun Int.times(other: C): C = polynomialRing { this@times * other }
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Polynomial-integer relation
|
||||||
|
/**
|
||||||
|
* Returns sum of the constant and the integer represented as polynomial.
|
||||||
|
*
|
||||||
|
* The operation is equivalent to adding [other] copies of unit polynomial to [this].
|
||||||
|
*/
|
||||||
|
public override operator fun P.plus(other: Int): P = polynomialRing { this@plus + other }
|
||||||
|
/**
|
||||||
|
* Returns difference between the constant and the integer represented as polynomial.
|
||||||
|
*
|
||||||
|
* The operation is equivalent to subtraction [other] copies of unit polynomial from [this].
|
||||||
|
*/
|
||||||
|
public override operator fun P.minus(other: Int): P = polynomialRing { this@minus - other }
|
||||||
|
/**
|
||||||
|
* Returns product of the constant and the integer represented as polynomial.
|
||||||
|
*
|
||||||
|
* The operation is equivalent to sum of [other] copies of [this].
|
||||||
|
*/
|
||||||
|
public override operator fun P.times(other: Int): P = polynomialRing { this@times * other }
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Integer-polynomial relation
|
||||||
|
/**
|
||||||
|
* Returns sum of the integer represented as polynomial and the constant.
|
||||||
|
*
|
||||||
|
* The operation is equivalent to adding [this] copies of unit polynomial to [other].
|
||||||
|
*/
|
||||||
|
public override operator fun Int.plus(other: P): P = polynomialRing { this@plus + other }
|
||||||
|
/**
|
||||||
|
* Returns difference between the integer represented as polynomial and the constant.
|
||||||
|
*
|
||||||
|
* The operation is equivalent to subtraction [this] copies of unit polynomial from [other].
|
||||||
|
*/
|
||||||
|
public override operator fun Int.minus(other: P): P = polynomialRing { this@minus - other }
|
||||||
|
/**
|
||||||
|
* Returns product of the integer represented as polynomial and the constant.
|
||||||
|
*
|
||||||
|
* The operation is equivalent to sum of [this] copies of [other].
|
||||||
|
*/
|
||||||
|
public override operator fun Int.times(other: P): P = polynomialRing { this@times * other }
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Constant-constant relation
|
||||||
|
/**
|
||||||
|
* Returns the same constant.
|
||||||
|
*/
|
||||||
|
@JvmName("constantUnaryPlus")
|
||||||
|
@JsName("constantUnaryPlus")
|
||||||
|
public override operator fun C.unaryPlus(): C = polynomialRing { +this@unaryPlus }
|
||||||
|
/**
|
||||||
|
* Returns negation of the constant.
|
||||||
|
*/
|
||||||
|
@JvmName("constantUnaryMinus")
|
||||||
|
@JsName("constantUnaryMinus")
|
||||||
|
public override operator fun C.unaryMinus(): C = polynomialRing { -this@unaryMinus }
|
||||||
|
/**
|
||||||
|
* Returns sum of the constants.
|
||||||
|
*/
|
||||||
|
@JvmName("constantPlus")
|
||||||
|
@JsName("constantPlus")
|
||||||
|
public override operator fun C.plus(other: C): C = polynomialRing { this@plus + other }
|
||||||
|
/**
|
||||||
|
* Returns difference of the constants.
|
||||||
|
*/
|
||||||
|
@JvmName("constantMinus")
|
||||||
|
@JsName("constantMinus")
|
||||||
|
public override operator fun C.minus(other: C): C = polynomialRing { this@minus - other }
|
||||||
|
/**
|
||||||
|
* Returns product of the constants.
|
||||||
|
*/
|
||||||
|
@JvmName("constantTimes")
|
||||||
|
@JsName("constantTimes")
|
||||||
|
public override operator fun C.times(other: C): C = polynomialRing { this@times * other }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the instant is zero constant.
|
||||||
|
*/
|
||||||
|
@JvmName("constantIsZero")
|
||||||
|
public override fun C.isZero(): Boolean = polynomialRing { this@isZero.isZero() }
|
||||||
|
/**
|
||||||
|
* Check if the instant is NOT zero constant.
|
||||||
|
*/
|
||||||
|
@JvmName("constantIsNotZero")
|
||||||
|
public override fun C.isNotZero(): Boolean = polynomialRing { this@isNotZero.isNotZero() }
|
||||||
|
/**
|
||||||
|
* Check if the instant is unit constant.
|
||||||
|
*/
|
||||||
|
@JvmName("constantIsOne")
|
||||||
|
public override fun C.isOne(): Boolean = polynomialRing { this@isOne.isOne() }
|
||||||
|
/**
|
||||||
|
* Check if the instant is NOT unit constant.
|
||||||
|
*/
|
||||||
|
@JvmName("constantIsNotOne")
|
||||||
|
public override fun C.isNotOne(): Boolean = polynomialRing { this@isNotOne.isNotOne() }
|
||||||
|
/**
|
||||||
|
* Check if the instant is minus unit constant.
|
||||||
|
*/
|
||||||
|
@JvmName("constantIsMinusOne")
|
||||||
|
public override fun C.isMinusOne(): Boolean = polynomialRing { this@isMinusOne.isMinusOne() }
|
||||||
|
/**
|
||||||
|
* Check if the instant is NOT minus unit constant.
|
||||||
|
*/
|
||||||
|
@JvmName("constantIsNotMinusOne")
|
||||||
|
public override fun C.isNotMinusOne(): Boolean = polynomialRing { this@isNotMinusOne.isNotMinusOne() }
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Constant-polynomial relation
|
||||||
|
/**
|
||||||
|
* Returns sum of the constant represented as polynomial and the polynomial.
|
||||||
|
*/
|
||||||
|
public override operator fun C.plus(other: P): P = polynomialRing { this@plus + other }
|
||||||
|
/**
|
||||||
|
* Returns difference between the constant represented as polynomial and the polynomial.
|
||||||
|
*/
|
||||||
|
public override operator fun C.minus(other: P): P = polynomialRing { this@minus - other }
|
||||||
|
/**
|
||||||
|
* Returns product of the constant represented as polynomial and the polynomial.
|
||||||
|
*/
|
||||||
|
public override operator fun C.times(other: P): P = polynomialRing { this@times * other }
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Polynomial-constant relation
|
||||||
|
/**
|
||||||
|
* Returns sum of the constant represented as polynomial and the polynomial.
|
||||||
|
*/
|
||||||
|
public override operator fun P.plus(other: C): P = polynomialRing { this@plus + other }
|
||||||
|
/**
|
||||||
|
* Returns difference between the constant represented as polynomial and the polynomial.
|
||||||
|
*/
|
||||||
|
public override operator fun P.minus(other: C): P = polynomialRing { this@minus - other }
|
||||||
|
/**
|
||||||
|
* Returns product of the constant represented as polynomial and the polynomial.
|
||||||
|
*/
|
||||||
|
public override operator fun P.times(other: C): P = polynomialRing { this@times * other }
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Polynomial-polynomial relation
|
||||||
|
/**
|
||||||
|
* Returns the same polynomial.
|
||||||
|
*/
|
||||||
|
public override operator fun P.unaryPlus(): P = polynomialRing { +this@unaryPlus }
|
||||||
|
/**
|
||||||
|
* Returns negation of the polynomial.
|
||||||
|
*/
|
||||||
|
public override operator fun P.unaryMinus(): P = polynomialRing { -this@unaryMinus }
|
||||||
|
/**
|
||||||
|
* Returns sum of the polynomials.
|
||||||
|
*/
|
||||||
|
public override operator fun P.plus(other: P): P = polynomialRing { this@plus + other }
|
||||||
|
/**
|
||||||
|
* Returns difference of the polynomials.
|
||||||
|
*/
|
||||||
|
public override operator fun P.minus(other: P): P = polynomialRing { this@minus - other }
|
||||||
|
/**
|
||||||
|
* Returns product of the polynomials.
|
||||||
|
*/
|
||||||
|
public override operator fun P.times(other: P): P = polynomialRing { this@times * other }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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).
|
||||||
|
*/
|
||||||
|
public override val polynomialZero: P get() = polynomialRing.zero
|
||||||
|
/**
|
||||||
|
* Instance of unit polynomial (unit of the polynomial ring).
|
||||||
|
*/
|
||||||
|
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 }
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// Not sure is it necessary...
|
||||||
|
// region Polynomial properties
|
||||||
|
/**
|
||||||
|
* 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() }
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
}
|
@ -13,7 +13,7 @@ import kotlin.math.max
|
|||||||
*
|
*
|
||||||
* @param C Ring in which the polynomial is considered.
|
* @param C Ring in which the polynomial is considered.
|
||||||
*/
|
*/
|
||||||
public class LabeledPolynomial<C>
|
public data class LabeledPolynomial<C>
|
||||||
internal constructor(
|
internal constructor(
|
||||||
/**
|
/**
|
||||||
* Map that collects coefficients of the polynomial. Every non-zero monomial
|
* Map that collects coefficients of the polynomial. Every non-zero monomial
|
||||||
@ -788,7 +788,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
isZero() -> zero
|
isZero() -> zero
|
||||||
other.isZero() -> zero
|
other.isZero() -> zero
|
||||||
else -> LabeledPolynomial<C>(
|
else -> LabeledPolynomial<C>(
|
||||||
buildCoefficients {
|
buildCoefficients(coefficients.size * other.coefficients.size) {
|
||||||
for ((degs1, c1) in coefficients) for ((degs2, c2) in other.coefficients) {
|
for ((degs1, c1) in coefficients) for ((degs2, c2) in other.coefficients) {
|
||||||
val degs = degs1.toMutableMap()
|
val degs = degs1.toMutableMap()
|
||||||
degs2.mapValuesTo(degs) { (variable, deg) -> degs.getOrElse(variable) { 0u } + deg }
|
degs2.mapValuesTo(degs) { (variable, deg) -> degs.getOrElse(variable) { 0u } + deg }
|
||||||
@ -804,7 +804,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
|
|
||||||
// TODO: Docs
|
// TODO: Docs
|
||||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals")
|
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals")
|
||||||
override fun LabeledPolynomial<C>.equals(other: LabeledPolynomial<C>): Boolean =
|
override infix fun LabeledPolynomial<C>.equalsTo(other: LabeledPolynomial<C>): Boolean =
|
||||||
when {
|
when {
|
||||||
this === other -> true
|
this === other -> true
|
||||||
else -> coefficients.size == other.coefficients.size &&
|
else -> coefficients.size == other.coefficients.size &&
|
||||||
@ -896,15 +896,9 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
// public inline operator fun LabeledPolynomial<C>.invoke(argument: Map<Variable, LabeledPolynomial<C>>): LabeledPolynomial<C> = this.substitute(ring, argument)
|
// public inline operator fun LabeledPolynomial<C>.invoke(argument: Map<Variable, LabeledPolynomial<C>>): LabeledPolynomial<C> = this.substitute(ring, argument)
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Legacy
|
|
||||||
@Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
|
||||||
override inline fun add(left: LabeledPolynomial<C>, right: LabeledPolynomial<C>): LabeledPolynomial<C> = left + right
|
|
||||||
@Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
|
||||||
override inline fun multiply(left: LabeledPolynomial<C>, right: LabeledPolynomial<C>): LabeledPolynomial<C> = left * right
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region Utilities
|
// region Utilities
|
||||||
// TODO: Move to region internal utilities with context receiver
|
// TODO: Move to region internal utilities with context receiver
|
||||||
|
@JvmName("applyAndRemoveZerosInternal")
|
||||||
internal fun MutableMap<Map<Variable, UInt>, C>.applyAndRemoveZeros(block: MutableMap<Map<Variable, UInt>, C>.() -> Unit) : MutableMap<Map<Variable, UInt>, C> {
|
internal fun MutableMap<Map<Variable, UInt>, C>.applyAndRemoveZeros(block: MutableMap<Map<Variable, UInt>, C>.() -> Unit) : MutableMap<Map<Variable, UInt>, C> {
|
||||||
contract {
|
contract {
|
||||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||||
@ -916,12 +910,20 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
internal fun Map<Map<Variable, UInt>, C>.applyAndRemoveZeros(block: MutableMap<Map<Variable, UInt>, C>.() -> Unit) : Map<Map<Variable, UInt>, C> =
|
internal fun Map<Map<Variable, UInt>, C>.applyAndRemoveZeros(block: MutableMap<Map<Variable, UInt>, C>.() -> Unit) : Map<Map<Variable, UInt>, C> =
|
||||||
toMutableMap().applyAndRemoveZeros(block)
|
toMutableMap().applyAndRemoveZeros(block)
|
||||||
@OptIn(ExperimentalTypeInference::class)
|
@OptIn(ExperimentalTypeInference::class)
|
||||||
internal fun buildCoefficients(@BuilderInference builderAction: MutableMap<Map<Variable, UInt>, C>.() -> Unit): Map<Map<Variable, UInt>, C> {
|
internal inline fun buildCoefficients(@BuilderInference builderAction: MutableMap<Map<Variable, UInt>, C>.() -> Unit): Map<Map<Variable, UInt>, C> {
|
||||||
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
|
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
|
||||||
return buildMap {
|
return buildMap {
|
||||||
builderAction()
|
builderAction()
|
||||||
for ((degs, c) in this) if (c.isZero()) this.remove(degs)
|
for ((degs, c) in this) if (c.isZero()) this.remove(degs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@OptIn(ExperimentalTypeInference::class)
|
||||||
|
internal inline fun buildCoefficients(capacity: Int, @BuilderInference builderAction: MutableMap<Map<Variable, UInt>, C>.() -> Unit): Map<Map<Variable, UInt>, C> {
|
||||||
|
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
|
||||||
|
return buildMap(capacity) {
|
||||||
|
builderAction()
|
||||||
|
for ((degs, c) in this) if (c.isZero()) this.remove(degs)
|
||||||
|
}
|
||||||
|
}
|
||||||
// endregion
|
// endregion
|
||||||
}
|
}
|
@ -13,7 +13,7 @@ import kotlin.math.max
|
|||||||
*
|
*
|
||||||
* @param C the type of constants.
|
* @param C the type of constants.
|
||||||
*/
|
*/
|
||||||
public class NumberedPolynomial<C>
|
public data class NumberedPolynomial<C>
|
||||||
internal constructor(
|
internal constructor(
|
||||||
/**
|
/**
|
||||||
* Map that collects coefficients of the polynomial. Every monomial `a x_1^{d_1} ... x_n^{d_n}` is represented as
|
* Map that collects coefficients of the polynomial. Every monomial `a x_1^{d_1} ... x_n^{d_n}` is represented as
|
||||||
@ -259,27 +259,9 @@ public fun <C, A: Ring<C>> C.asNumberedPolynomial() : NumberedPolynomial<C> = Nu
|
|||||||
* @param ring the [A] instance.
|
* @param ring the [A] instance.
|
||||||
*/
|
*/
|
||||||
@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE", "INAPPLICABLE_JVM_NAME")
|
@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE", "INAPPLICABLE_JVM_NAME")
|
||||||
public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
||||||
public val ring: A,
|
public final override val ring: A,
|
||||||
) : AbstractPolynomialSpace<C, NumberedPolynomial<C>> {
|
) : AbstractPolynomialSpaceOverRing<C, NumberedPolynomial<C>, A> {
|
||||||
// region Constant-integer relation
|
|
||||||
@JvmName("constantIntPlus")
|
|
||||||
public override operator fun C.plus(other: Int): C = ring { optimizedAddMultiplied(this@plus, one, other) }
|
|
||||||
@JvmName("constantIntMinus")
|
|
||||||
public override operator fun C.minus(other: Int): C = ring { optimizedAddMultiplied(this@minus, one, -other) }
|
|
||||||
@JvmName("constantIntTimes")
|
|
||||||
public override operator fun C.times(other: Int): C = ring { optimizedMultiply(this@times, other) }
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region Integer-constant relation
|
|
||||||
@JvmName("intConstantPlus")
|
|
||||||
public override operator fun Int.plus(other: C): C = ring { optimizedAddMultiplied(other, one, this@plus) }
|
|
||||||
@JvmName("intConstantMinus")
|
|
||||||
public override operator fun Int.minus(other: C): C = ring { optimizedAddMultiplied(-other, one, this@minus) }
|
|
||||||
@JvmName("intConstantTimes")
|
|
||||||
public override operator fun Int.times(other: C): C = ring { optimizedMultiply(other, this@times) }
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region Polynomial-integer relation
|
// region Polynomial-integer relation
|
||||||
public override operator fun NumberedPolynomial<C>.plus(other: Int): NumberedPolynomial<C> =
|
public override operator fun NumberedPolynomial<C>.plus(other: Int): NumberedPolynomial<C> =
|
||||||
if (other == 0) this
|
if (other == 0) this
|
||||||
@ -362,29 +344,6 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
)
|
)
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Constant-constant relation
|
|
||||||
@JvmName("constantUnaryMinus")
|
|
||||||
override operator fun C.unaryMinus(): C = ring { -this@unaryMinus }
|
|
||||||
@JvmName("constantPlus")
|
|
||||||
override operator fun C.plus(other: C): C = ring { this@plus + other }
|
|
||||||
@JvmName("constantMinus")
|
|
||||||
override operator fun C.minus(other: C): C = ring { this@minus - other }
|
|
||||||
@JvmName("constantTimes")
|
|
||||||
override operator fun C.times(other: C): C = ring { this@times * other }
|
|
||||||
@JvmName("constantIsZero")
|
|
||||||
public override fun C.isZero(): Boolean = ring { this == zero }
|
|
||||||
@JvmName("constantIsNotZero")
|
|
||||||
public override fun C.isNotZero(): Boolean = ring { this != zero }
|
|
||||||
@JvmName("constantIsOne")
|
|
||||||
public override fun C.isOne(): Boolean = ring { this == one }
|
|
||||||
@JvmName("constantIsNotOne")
|
|
||||||
public override fun C.isNotOne(): Boolean = ring { this != one }
|
|
||||||
@JvmName("constantIsMinusOne")
|
|
||||||
public override fun C.isMinusOne(): Boolean = ring { this == -one }
|
|
||||||
@JvmName("constantIsNotMinusOne")
|
|
||||||
public override fun C.isNotMinusOne(): Boolean = ring { this != -one }
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region Constant-polynomial relation
|
// region Constant-polynomial relation
|
||||||
override operator fun C.plus(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
override operator fun C.plus(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
||||||
if (this.isZero()) other
|
if (this.isZero()) other
|
||||||
@ -521,7 +480,7 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
other.isZero() -> zero
|
other.isZero() -> zero
|
||||||
else ->
|
else ->
|
||||||
NumberedPolynomial<C>(
|
NumberedPolynomial<C>(
|
||||||
buildCoefficients {
|
buildCoefficients(coefficients.size * other.coefficients.size) {
|
||||||
for ((degs1, c1) in coefficients) for ((degs2, c2) in other.coefficients) {
|
for ((degs1, c1) in coefficients) for ((degs2, c2) in other.coefficients) {
|
||||||
val degs =
|
val degs =
|
||||||
(0..max(degs1.lastIndex, degs2.lastIndex))
|
(0..max(degs1.lastIndex, degs2.lastIndex))
|
||||||
@ -534,7 +493,6 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override fun NumberedPolynomial<C>.isZero(): Boolean = coefficients.values.all { it.isZero() }
|
public override fun NumberedPolynomial<C>.isZero(): Boolean = coefficients.values.all { it.isZero() }
|
||||||
public override fun NumberedPolynomial<C>.isNotZero(): Boolean = coefficients.values.any { it.isNotZero() }
|
|
||||||
public override fun NumberedPolynomial<C>.isOne(): Boolean =
|
public override fun NumberedPolynomial<C>.isOne(): Boolean =
|
||||||
with(coefficients) {
|
with(coefficients) {
|
||||||
var foundAbsoluteTermAndItIsOne = false
|
var foundAbsoluteTermAndItIsOne = false
|
||||||
@ -547,7 +505,6 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
}
|
}
|
||||||
foundAbsoluteTermAndItIsOne
|
foundAbsoluteTermAndItIsOne
|
||||||
}
|
}
|
||||||
public override fun NumberedPolynomial<C>.isNotOne(): Boolean = !isOne()
|
|
||||||
public override fun NumberedPolynomial<C>.isMinusOne(): Boolean =
|
public override fun NumberedPolynomial<C>.isMinusOne(): Boolean =
|
||||||
with(coefficients) {
|
with(coefficients) {
|
||||||
var foundAbsoluteTermAndItIsMinusOne = false
|
var foundAbsoluteTermAndItIsMinusOne = false
|
||||||
@ -560,7 +517,6 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
}
|
}
|
||||||
foundAbsoluteTermAndItIsMinusOne
|
foundAbsoluteTermAndItIsMinusOne
|
||||||
}
|
}
|
||||||
public override fun NumberedPolynomial<C>.isNotMinusOne(): Boolean = !isMinusOne()
|
|
||||||
|
|
||||||
override val zero: NumberedPolynomial<C> = NumberedPolynomial<C>(emptyMap())
|
override val zero: NumberedPolynomial<C> = NumberedPolynomial<C>(emptyMap())
|
||||||
override val one: NumberedPolynomial<C> =
|
override val one: NumberedPolynomial<C> =
|
||||||
@ -572,7 +528,7 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
|
|
||||||
// TODO: Docs
|
// TODO: Docs
|
||||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals")
|
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals")
|
||||||
override fun NumberedPolynomial<C>.equals(other: NumberedPolynomial<C>): Boolean =
|
override infix fun NumberedPolynomial<C>.equalsTo(other: NumberedPolynomial<C>): Boolean =
|
||||||
when {
|
when {
|
||||||
this === other -> true
|
this === other -> true
|
||||||
else -> coefficients.size == other.coefficients.size &&
|
else -> coefficients.size == other.coefficients.size &&
|
||||||
@ -658,15 +614,9 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
public inline operator fun NumberedPolynomial<C>.invoke(argument: Map<Int, NumberedPolynomial<C>>): NumberedPolynomial<C> = this.substitute(ring, argument)
|
public inline operator fun NumberedPolynomial<C>.invoke(argument: Map<Int, NumberedPolynomial<C>>): NumberedPolynomial<C> = this.substitute(ring, argument)
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Legacy
|
|
||||||
@Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
|
||||||
override inline fun add(left: NumberedPolynomial<C>, right: NumberedPolynomial<C>): NumberedPolynomial<C> = left + right
|
|
||||||
@Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
|
||||||
override inline fun multiply(left: NumberedPolynomial<C>, right: NumberedPolynomial<C>): NumberedPolynomial<C> = left * right
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region Utilities
|
// region Utilities
|
||||||
// TODO: Move to region internal utilities with context receiver
|
// TODO: Move to region internal utilities with context receiver
|
||||||
|
@JvmName("applyAndRemoveZerosInternal")
|
||||||
internal fun MutableMap<List<UInt>, C>.applyAndRemoveZeros(block: MutableMap<List<UInt>, C>.() -> Unit) : MutableMap<List<UInt>, C> {
|
internal fun MutableMap<List<UInt>, C>.applyAndRemoveZeros(block: MutableMap<List<UInt>, C>.() -> Unit) : MutableMap<List<UInt>, C> {
|
||||||
contract {
|
contract {
|
||||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||||
@ -678,12 +628,20 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
internal fun Map<List<UInt>, C>.applyAndRemoveZeros(block: MutableMap<List<UInt>, C>.() -> Unit) : Map<List<UInt>, C> =
|
internal fun Map<List<UInt>, C>.applyAndRemoveZeros(block: MutableMap<List<UInt>, C>.() -> Unit) : Map<List<UInt>, C> =
|
||||||
toMutableMap().applyAndRemoveZeros(block)
|
toMutableMap().applyAndRemoveZeros(block)
|
||||||
@OptIn(ExperimentalTypeInference::class)
|
@OptIn(ExperimentalTypeInference::class)
|
||||||
internal fun buildCoefficients(@BuilderInference builderAction: MutableMap<List<UInt>, C>.() -> Unit): Map<List<UInt>, C> {
|
internal inline fun buildCoefficients(@BuilderInference builderAction: MutableMap<List<UInt>, C>.() -> Unit): Map<List<UInt>, C> {
|
||||||
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
|
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
|
||||||
return buildMap {
|
return buildMap {
|
||||||
builderAction()
|
builderAction()
|
||||||
for ((degs, c) in this) if (c.isZero()) this.remove(degs)
|
for ((degs, c) in this) if (c.isZero()) this.remove(degs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@OptIn(ExperimentalTypeInference::class)
|
||||||
|
internal inline fun buildCoefficients(capacity: Int, @BuilderInference builderAction: MutableMap<List<UInt>, C>.() -> Unit): Map<List<UInt>, C> {
|
||||||
|
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
|
||||||
|
return buildMap(capacity) {
|
||||||
|
builderAction()
|
||||||
|
for ((degs, c) in this) if (c.isZero()) this.remove(degs)
|
||||||
|
}
|
||||||
|
}
|
||||||
// endregion
|
// endregion
|
||||||
}
|
}
|
@ -15,7 +15,7 @@ import kotlin.math.min
|
|||||||
*
|
*
|
||||||
* @param coefficients constant is the leftmost coefficient.
|
* @param coefficients constant is the leftmost coefficient.
|
||||||
*/
|
*/
|
||||||
public class Polynomial<T>(public val coefficients: List<T>) : AbstractPolynomial<T> {
|
public data class Polynomial<T>(public val coefficients: List<T>) : AbstractPolynomial<T> {
|
||||||
override fun toString(): String = "Polynomial$coefficients"
|
override fun toString(): String = "Polynomial$coefficients"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,25 +69,8 @@ public fun <T> T.asPolynomial() : Polynomial<T> = Polynomial(listOf(this))
|
|||||||
*/
|
*/
|
||||||
@Suppress("INAPPLICABLE_JVM_NAME") // TODO: KT-31420
|
@Suppress("INAPPLICABLE_JVM_NAME") // TODO: KT-31420
|
||||||
public open class PolynomialSpace<C, A : Ring<C>>(
|
public open class PolynomialSpace<C, A : Ring<C>>(
|
||||||
public val ring: A,
|
public final override val ring: A,
|
||||||
) : AbstractPolynomialSpace<C, Polynomial<C>> {
|
) : AbstractPolynomialSpaceOverRing<C, Polynomial<C>, A> {
|
||||||
// region Constant-integer relation
|
|
||||||
@JvmName("constantIntPlus")
|
|
||||||
public override operator fun C.plus(other: Int): C = ring { optimizedAddMultiplied(this@plus, one, other) }
|
|
||||||
@JvmName("constantIntMinus")
|
|
||||||
public override operator fun C.minus(other: Int): C = ring { optimizedAddMultiplied(this@minus, one, -other) }
|
|
||||||
@JvmName("constantIntTimes")
|
|
||||||
public override operator fun C.times(other: Int): C = ring { optimizedMultiply(this@times, other) }
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region Integer-constant relation
|
|
||||||
@JvmName("intConstantPlus")
|
|
||||||
public override operator fun Int.plus(other: C): C = ring { optimizedAddMultiplied(other, one, this@plus) }
|
|
||||||
@JvmName("intConstantMinus")
|
|
||||||
public override operator fun Int.minus(other: C): C = ring { optimizedAddMultiplied(-other, one, this@minus) }
|
|
||||||
@JvmName("intConstantTimes")
|
|
||||||
public override operator fun Int.times(other: C): C = ring { optimizedMultiply(other, this@times) }
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region Polynomial-integer relation
|
// region Polynomial-integer relation
|
||||||
public override operator fun Polynomial<C>.plus(other: Int): Polynomial<C> =
|
public override operator fun Polynomial<C>.plus(other: Int): Polynomial<C> =
|
||||||
@ -179,29 +162,6 @@ public open class PolynomialSpace<C, A : Ring<C>>(
|
|||||||
)
|
)
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Constant-constant relation
|
|
||||||
@JvmName("constantUnaryMinus")
|
|
||||||
public override operator fun C.unaryMinus(): C = ring { -this@unaryMinus }
|
|
||||||
@JvmName("constantPlus")
|
|
||||||
public override operator fun C.plus(other: C): C = ring { this@plus + other }
|
|
||||||
@JvmName("constantMinus")
|
|
||||||
public override operator fun C.minus(other: C): C = ring { this@minus - other }
|
|
||||||
@JvmName("constantTimes")
|
|
||||||
public override operator fun C.times(other: C): C = ring { this@times * other }
|
|
||||||
@JvmName("constantIsZero")
|
|
||||||
public override fun C.isZero(): Boolean = ring { this == zero }
|
|
||||||
@JvmName("constantIsNotZero")
|
|
||||||
public override fun C.isNotZero(): Boolean = ring { this != zero }
|
|
||||||
@JvmName("constantIsOne")
|
|
||||||
public override fun C.isOne(): Boolean = ring { this == one }
|
|
||||||
@JvmName("constantIsNotOne")
|
|
||||||
public override fun C.isNotOne(): Boolean = ring { this != one }
|
|
||||||
@JvmName("constantIsMinusOne")
|
|
||||||
public override fun C.isMinusOne(): Boolean = ring { this == -one }
|
|
||||||
@JvmName("constantIsNotMinusOne")
|
|
||||||
public override fun C.isNotMinusOne(): Boolean = ring { this != -one }
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region Constant-polynomial relation
|
// region Constant-polynomial relation
|
||||||
public override operator fun C.plus(other: Polynomial<C>): Polynomial<C> =
|
public override operator fun C.plus(other: Polynomial<C>): Polynomial<C> =
|
||||||
if (this.isZero()) other
|
if (this.isZero()) other
|
||||||
@ -355,19 +315,16 @@ public open class PolynomialSpace<C, A : Ring<C>>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override fun Polynomial<C>.isZero(): Boolean = coefficients.all { it.isZero() }
|
public override fun Polynomial<C>.isZero(): Boolean = coefficients.all { it.isZero() }
|
||||||
public override fun Polynomial<C>.isNotZero(): Boolean = coefficients.any { it.isNotZero() }
|
|
||||||
public override fun Polynomial<C>.isOne(): Boolean =
|
public override fun Polynomial<C>.isOne(): Boolean =
|
||||||
with(coefficients) { isNotEmpty() && asSequence().withIndex().any { (index, c) -> if (index == 0) c.isOne() else c.isZero() } } // TODO: It's better to write new methods like `anyIndexed`. But what's better way to do it?
|
with(coefficients) { isNotEmpty() && asSequence().withIndex().any { (index, c) -> if (index == 0) c.isOne() else c.isZero() } } // TODO: It's better to write new methods like `anyIndexed`. But what's better way to do it?
|
||||||
public override fun Polynomial<C>.isNotOne(): Boolean = !isOne()
|
|
||||||
public override fun Polynomial<C>.isMinusOne(): Boolean =
|
public override fun Polynomial<C>.isMinusOne(): Boolean =
|
||||||
with(coefficients) { isNotEmpty() && asSequence().withIndex().any { (index, c) -> if (index == 0) c.isMinusOne() else c.isZero() } } // TODO: It's better to write new methods like `anyIndexed`. But what's better way to do it?
|
with(coefficients) { isNotEmpty() && asSequence().withIndex().any { (index, c) -> if (index == 0) c.isMinusOne() else c.isZero() } } // TODO: It's better to write new methods like `anyIndexed`. But what's better way to do it?
|
||||||
public override fun Polynomial<C>.isNotMinusOne(): Boolean = !isMinusOne()
|
|
||||||
|
|
||||||
override val zero: Polynomial<C> = Polynomial(emptyList())
|
override val zero: Polynomial<C> = Polynomial(emptyList())
|
||||||
override val one: Polynomial<C> = Polynomial(listOf(ring.one))
|
override val one: Polynomial<C> = Polynomial(listOf(ring.one))
|
||||||
|
|
||||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals")
|
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals")
|
||||||
public override fun Polynomial<C>.equals(other: Polynomial<C>): Boolean =
|
public override infix fun Polynomial<C>.equalsTo(other: Polynomial<C>): Boolean =
|
||||||
when {
|
when {
|
||||||
this === other -> true
|
this === other -> true
|
||||||
else -> {
|
else -> {
|
||||||
|
@ -0,0 +1,355 @@
|
|||||||
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
|
import space.kscience.kmath.operations.*
|
||||||
|
import kotlin.jvm.JvmName
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
|
|
||||||
|
public data class RationalFunction<C> internal constructor (
|
||||||
|
public override val numerator: Polynomial<C>,
|
||||||
|
public override val denominator: Polynomial<C>
|
||||||
|
) : AbstractRationalFunction<C, Polynomial<C>> {
|
||||||
|
override fun toString(): String = "RationalFunction${numerator.coefficients}/${denominator.coefficients}"
|
||||||
|
}
|
||||||
|
|
||||||
|
// region Internal utilities
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents internal [RationalFunction] errors.
|
||||||
|
*/
|
||||||
|
internal class RationalFunctionError : Error {
|
||||||
|
constructor(): super()
|
||||||
|
constructor(message: String): super(message)
|
||||||
|
constructor(message: String?, cause: Throwable?): super(message, cause)
|
||||||
|
constructor(cause: Throwable?): super(cause)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throws an [RationalFunction] with the given [message].
|
||||||
|
*/
|
||||||
|
internal fun rationalFunctionError(message: Any): Nothing = throw RationalFunctionError(message.toString())
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Constructors and converters
|
||||||
|
// Waiting for context receivers :( TODO: Replace with context receivers when they will be available
|
||||||
|
|
||||||
|
//context(RationalFunctionSpace<C, A>)
|
||||||
|
//@Suppress("FunctionName")
|
||||||
|
//internal fun <C, A: Ring<C>> RationalFunction(numerator: Polynomial<C>, denominator: Polynomial<C>): RationalFunction<C> =
|
||||||
|
// if (denominator.isZero()) throw ArithmeticException("/ by zero")
|
||||||
|
// else RationalFunction<C>(numerator, denominator)
|
||||||
|
//context(RationalFunctionSpace<C, A>)
|
||||||
|
//@Suppress("FunctionName")
|
||||||
|
//public fun <C, A: Ring<C>> RationalFunction(numeratorCoefficients: List<C>, denominatorCoefficients: List<C>, reverse: Boolean = false): RationalFunction<C> =
|
||||||
|
// RationalFunction<C>(
|
||||||
|
// Polynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ),
|
||||||
|
// Polynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } ).also { if (it.isZero()) }
|
||||||
|
// )
|
||||||
|
//context(RationalFunctionSpace<C, A>)
|
||||||
|
//@Suppress("FunctionName")
|
||||||
|
//public fun <C, A: Ring<C>> RationalFunction(numerator: Polynomial<C>): RationalFunction<C> =
|
||||||
|
// RationalFunction(numerator, onePolynomial)
|
||||||
|
//context(RationalFunctionSpace<C, A>)
|
||||||
|
//@Suppress("FunctionName")
|
||||||
|
//public fun <C, A: Ring<C>> RationalFunction(numeratorCoefficients: List<C>, reverse: Boolean = false): RationalFunction<C> =
|
||||||
|
// RationalFunction(
|
||||||
|
// Polynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } )
|
||||||
|
// )
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
public class RationalFunctionSpace<C, A : Ring<C>> (
|
||||||
|
public val ring: A,
|
||||||
|
) : AbstractRationalFunctionalSpaceOverPolynomialSpace<C, Polynomial<C>, RationalFunction<C>, A> {
|
||||||
|
|
||||||
|
override val polynomialRing : PolynomialSpace<C, A> = PolynomialSpace(ring)
|
||||||
|
|
||||||
|
// region Rational-integer relation
|
||||||
|
/**
|
||||||
|
* Returns sum of the rational function and the integer represented as rational function.
|
||||||
|
*
|
||||||
|
* The operation is equivalent to adding [other] copies of unit polynomial to [this].
|
||||||
|
*/
|
||||||
|
public override operator fun RationalFunction<C>.plus(other: Int): RationalFunction<C> =
|
||||||
|
RationalFunction(
|
||||||
|
numerator + denominator * other,
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns difference between the rational function and the integer represented as rational function.
|
||||||
|
*
|
||||||
|
* The operation is equivalent to subtraction [other] copies of unit polynomial from [this].
|
||||||
|
*/
|
||||||
|
public override operator fun RationalFunction<C>.minus(other: Int): RationalFunction<C> =
|
||||||
|
RationalFunction(
|
||||||
|
numerator - denominator * other,
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns product of the rational function and the integer represented as rational function.
|
||||||
|
*
|
||||||
|
* The operation is equivalent to sum of [other] copies of [this].
|
||||||
|
*/
|
||||||
|
public override operator fun RationalFunction<C>.times(other: Int): RationalFunction<C> =
|
||||||
|
RationalFunction(
|
||||||
|
numerator * other,
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Integer-Rational relation
|
||||||
|
/**
|
||||||
|
* Returns sum of the integer represented as rational function and the rational function.
|
||||||
|
*
|
||||||
|
* The operation is equivalent to adding [this] copies of unit polynomial to [other].
|
||||||
|
*/
|
||||||
|
public override operator fun Int.plus(other: RationalFunction<C>): RationalFunction<C> = TODO()
|
||||||
|
/**
|
||||||
|
* Returns difference between the integer represented as rational function and the rational function.
|
||||||
|
*
|
||||||
|
* The operation is equivalent to subtraction [this] copies of unit polynomial from [other].
|
||||||
|
*/
|
||||||
|
public override operator fun Int.minus(other: RationalFunction<C>): RationalFunction<C> = TODO()
|
||||||
|
/**
|
||||||
|
* Returns product of the integer represented as rational function and the rational function.
|
||||||
|
*
|
||||||
|
* The operation is equivalent to sum of [this] copies of [other].
|
||||||
|
*/
|
||||||
|
public override operator fun Int.times(other: RationalFunction<C>): RationalFunction<C> = TODO()
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Constant-rational relation
|
||||||
|
/**
|
||||||
|
* Returns sum of the constant represented as rational function and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun C.plus(other: RationalFunction<C>): RationalFunction<C> = TODO()
|
||||||
|
/**
|
||||||
|
* Returns difference between the constant represented as polynomial and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun C.minus(other: RationalFunction<C>): RationalFunction<C> = TODO()
|
||||||
|
/**
|
||||||
|
* Returns product of the constant represented as polynomial and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun C.times(other: RationalFunction<C>): RationalFunction<C> = TODO()
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Rational-constant relation
|
||||||
|
/**
|
||||||
|
* Returns sum of the constant represented as rational function and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun RationalFunction<C>.plus(other: C): RationalFunction<C> =
|
||||||
|
RationalFunction(
|
||||||
|
numerator + denominator * other,
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns difference between the constant represented as rational function and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun RationalFunction<C>.minus(other: C): RationalFunction<C> =
|
||||||
|
RationalFunction(
|
||||||
|
numerator - denominator * other,
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns product of the constant represented as rational function and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun RationalFunction<C>.times(other: C): RationalFunction<C> =
|
||||||
|
RationalFunction(
|
||||||
|
numerator * other,
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Polynomial-rational relation
|
||||||
|
/**
|
||||||
|
* Returns sum of the polynomial represented as rational function and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun Polynomial<C>.plus(other: RationalFunction<C>): RationalFunction<C> = TODO()
|
||||||
|
/**
|
||||||
|
* Returns difference between the polynomial represented as polynomial and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun Polynomial<C>.minus(other: RationalFunction<C>): RationalFunction<C> = TODO()
|
||||||
|
/**
|
||||||
|
* Returns product of the polynomial represented as polynomial and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun Polynomial<C>.times(other: RationalFunction<C>): RationalFunction<C> = TODO()
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Rational-polynomial relation
|
||||||
|
/**
|
||||||
|
* Returns sum of the polynomial represented as rational function and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun RationalFunction<C>.plus(other: Polynomial<C>): RationalFunction<C> =
|
||||||
|
RationalFunction(
|
||||||
|
numerator + denominator * other,
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns difference between the polynomial represented as rational function and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun RationalFunction<C>.minus(other: Polynomial<C>): RationalFunction<C> =
|
||||||
|
RationalFunction(
|
||||||
|
numerator - denominator * other,
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns product of the polynomial represented as rational function and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun RationalFunction<C>.times(other: Polynomial<C>): RationalFunction<C> =
|
||||||
|
RationalFunction(
|
||||||
|
numerator * other,
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Rational-rational relation
|
||||||
|
/**
|
||||||
|
* Returns negation of the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun RationalFunction<C>.unaryMinus(): RationalFunction<C> = RationalFunction(-numerator, denominator)
|
||||||
|
/**
|
||||||
|
* Returns sum of the rational functions.
|
||||||
|
*/
|
||||||
|
public override operator fun RationalFunction<C>.plus(other: RationalFunction<C>): RationalFunction<C> =
|
||||||
|
RationalFunction(
|
||||||
|
numerator * other.denominator + denominator * other.numerator,
|
||||||
|
denominator * other.denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns difference of the rational functions.
|
||||||
|
*/
|
||||||
|
public override operator fun RationalFunction<C>.minus(other: RationalFunction<C>): RationalFunction<C> =
|
||||||
|
RationalFunction(
|
||||||
|
numerator * other.denominator - denominator * other.numerator,
|
||||||
|
denominator * other.denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns product of the rational functions.
|
||||||
|
*/
|
||||||
|
public override operator fun RationalFunction<C>.times(other: RationalFunction<C>): RationalFunction<C> =
|
||||||
|
RationalFunction(
|
||||||
|
numerator * other.numerator,
|
||||||
|
denominator * other.denominator
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the instant is zero rational function.
|
||||||
|
*/
|
||||||
|
public override fun RationalFunction<C>.isZero(): Boolean = numerator.isZero()
|
||||||
|
/**
|
||||||
|
* Check if the instant is unit rational function.
|
||||||
|
*/
|
||||||
|
public override fun RationalFunction<C>.isOne(): Boolean = numerator.equalsTo(denominator)
|
||||||
|
/**
|
||||||
|
* Check if the instant is minus unit rational function.
|
||||||
|
*/
|
||||||
|
public override fun RationalFunction<C>.isMinusOne(): Boolean = (numerator + denominator).isZero()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance of zero rational function (zero of the rational functions ring).
|
||||||
|
*/
|
||||||
|
public override val zero: RationalFunction<C> = RationalFunction(polynomialZero, polynomialOne)
|
||||||
|
/**
|
||||||
|
* Instance of unit polynomial (unit of the rational functions ring).
|
||||||
|
*/
|
||||||
|
public override val one: RationalFunction<C> = RationalFunction(polynomialOne, polynomialOne)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks equality of the rational functions.
|
||||||
|
*/
|
||||||
|
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals")
|
||||||
|
public override infix fun RationalFunction<C>.equalsTo(other: RationalFunction<C>): Boolean =
|
||||||
|
when {
|
||||||
|
this === other -> true
|
||||||
|
numeratorDegree - denominatorDegree != with(other) { numeratorDegree - denominatorDegree } -> false
|
||||||
|
else -> numerator * other.denominator equalsTo other.numerator * denominator
|
||||||
|
}
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region REST TODO: Разобрать
|
||||||
|
|
||||||
|
public operator fun RationalFunction<C>.div(other: RationalFunction<C>): RationalFunction<C> =
|
||||||
|
RationalFunction(
|
||||||
|
numerator * other.denominator,
|
||||||
|
denominator * other.numerator
|
||||||
|
)
|
||||||
|
|
||||||
|
public operator fun RationalFunction<C>.div(other: Polynomial<C>): RationalFunction<C> =
|
||||||
|
RationalFunction(
|
||||||
|
numerator,
|
||||||
|
denominator * other
|
||||||
|
)
|
||||||
|
|
||||||
|
public operator fun RationalFunction<C>.div(other: C): RationalFunction<C> =
|
||||||
|
RationalFunction(
|
||||||
|
numerator,
|
||||||
|
denominator * other
|
||||||
|
)
|
||||||
|
|
||||||
|
public operator fun RationalFunction<C>.div(other: Int): RationalFunction<C> =
|
||||||
|
RationalFunction(
|
||||||
|
numerator,
|
||||||
|
denominator * other
|
||||||
|
)
|
||||||
|
|
||||||
|
// operator fun invoke(arg: UnivariatePolynomial<T>): RationalFunction<T> =
|
||||||
|
// RationalFunction(
|
||||||
|
// numerator(arg),
|
||||||
|
// denominator(arg)
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// operator fun invoke(arg: RationalFunction<T>): RationalFunction<T> {
|
||||||
|
// val num = numerator invokeRFTakeNumerator arg
|
||||||
|
// val den = denominator invokeRFTakeNumerator arg
|
||||||
|
// val degreeDif = numeratorDegree - denominatorDegree
|
||||||
|
// return if (degreeDif > 0)
|
||||||
|
// RationalFunction(
|
||||||
|
// num,
|
||||||
|
// multiplyByPower(den, arg.denominator, degreeDif)
|
||||||
|
// )
|
||||||
|
// else
|
||||||
|
// RationalFunction(
|
||||||
|
// multiplyByPower(num, arg.denominator, -degreeDif),
|
||||||
|
// den
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun toString(): String = toString(UnivariatePolynomial.variableName)
|
||||||
|
//
|
||||||
|
// fun toString(withVariableName: String = UnivariatePolynomial.variableName): String =
|
||||||
|
// when(true) {
|
||||||
|
// numerator.isZero() -> "0"
|
||||||
|
// denominator.isOne() -> numerator.toString(withVariableName)
|
||||||
|
// else -> "${numerator.toStringWithBrackets(withVariableName)}/${denominator.toStringWithBrackets(withVariableName)}"
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun toStringWithBrackets(withVariableName: String = UnivariatePolynomial.variableName): String =
|
||||||
|
// when(true) {
|
||||||
|
// numerator.isZero() -> "0"
|
||||||
|
// denominator.isOne() -> numerator.toStringWithBrackets(withVariableName)
|
||||||
|
// else -> "(${numerator.toStringWithBrackets(withVariableName)}/${denominator.toStringWithBrackets(withVariableName)})"
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun toReversedString(withVariableName: String = UnivariatePolynomial.variableName): String =
|
||||||
|
// when(true) {
|
||||||
|
// numerator.isZero() -> "0"
|
||||||
|
// denominator.isOne() -> numerator.toReversedString(withVariableName)
|
||||||
|
// else -> "${numerator.toReversedStringWithBrackets(withVariableName)}/${denominator.toReversedStringWithBrackets(withVariableName)}"
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun toReversedStringWithBrackets(withVariableName: String = UnivariatePolynomial.variableName): String =
|
||||||
|
// when(true) {
|
||||||
|
// numerator.isZero() -> "0"
|
||||||
|
// denominator.isOne() -> numerator.toReversedStringWithBrackets(withVariableName)
|
||||||
|
// else -> "(${numerator.toReversedStringWithBrackets(withVariableName)}/${denominator.toReversedStringWithBrackets(withVariableName)})"
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun removeZeros() =
|
||||||
|
// RationalFunction(
|
||||||
|
// numerator.removeZeros(),
|
||||||
|
// denominator.removeZeros()
|
||||||
|
// )
|
||||||
|
// endregion
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
|
|
||||||
|
// region Operator extensions
|
||||||
|
|
||||||
|
// region Field case
|
||||||
|
|
||||||
|
//operator fun <T: Field<T>> RationalFunction<T>.invoke(arg: T): T = numerator(arg) / denominator(arg)
|
||||||
|
//
|
||||||
|
//fun <T: Field<T>> RationalFunction<T>.reduced(): RationalFunction<T> =
|
||||||
|
// polynomialGCD(numerator, denominator).let {
|
||||||
|
// RationalFunction(
|
||||||
|
// numerator / it,
|
||||||
|
// denominator / it
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Derivatives
|
||||||
|
///**
|
||||||
|
// * Returns result of applying formal derivative to the polynomial.
|
||||||
|
// *
|
||||||
|
// * @param T Field where we are working now.
|
||||||
|
// * @return Result of the operator.
|
||||||
|
// */
|
||||||
|
//fun <T: Ring<T>> RationalFunction<T>.derivative() =
|
||||||
|
// RationalFunction(
|
||||||
|
// numerator.derivative() * denominator - denominator.derivative() * numerator,
|
||||||
|
// denominator * denominator
|
||||||
|
// )
|
||||||
|
// endregion
|
Loading…
Reference in New Issue
Block a user