1. Prototyped rest 2 algebraic structures of rational functions
2. Added `constantZero` and `constantOne` to abstract spaces and applied them instead of `ring.zero` and `ring.one`
3. Moved logic of `R.isZero` and 5 others to `AbstractRationalFunctionalSpace`
4. Deleted forgotten overridden functions of constants
5. Added KMath contributors' copyright notes
6. Added TODO 😄 The `NumberedPolynomial`'s `countOfVariables` is a confusing
This commit is contained in:
parent
07f4b83722
commit
dd820da765
@ -149,7 +149,7 @@ public interface AbstractPolynomialSpace<C, P: AbstractPolynomial<C>> : Ring<P>
|
|||||||
* Check if the instant is zero constant.
|
* Check if the instant is zero constant.
|
||||||
*/
|
*/
|
||||||
@JvmName("constantIsZero")
|
@JvmName("constantIsZero")
|
||||||
public fun C.isZero(): Boolean
|
public fun C.isZero(): Boolean = this == constantZero
|
||||||
/**
|
/**
|
||||||
* Check if the instant is NOT zero constant.
|
* Check if the instant is NOT zero constant.
|
||||||
*/
|
*/
|
||||||
@ -159,7 +159,7 @@ public interface AbstractPolynomialSpace<C, P: AbstractPolynomial<C>> : Ring<P>
|
|||||||
* Check if the instant is unit constant.
|
* Check if the instant is unit constant.
|
||||||
*/
|
*/
|
||||||
@JvmName("constantIsOne")
|
@JvmName("constantIsOne")
|
||||||
public fun C.isOne(): Boolean
|
public fun C.isOne(): Boolean = this == constantOne
|
||||||
/**
|
/**
|
||||||
* Check if the instant is NOT unit constant.
|
* Check if the instant is NOT unit constant.
|
||||||
*/
|
*/
|
||||||
@ -169,12 +169,21 @@ public interface AbstractPolynomialSpace<C, P: AbstractPolynomial<C>> : Ring<P>
|
|||||||
* Check if the instant is minus unit constant.
|
* Check if the instant is minus unit constant.
|
||||||
*/
|
*/
|
||||||
@JvmName("constantIsMinusOne")
|
@JvmName("constantIsMinusOne")
|
||||||
public fun C.isMinusOne(): Boolean
|
public fun C.isMinusOne(): Boolean = this == -constantOne
|
||||||
/**
|
/**
|
||||||
* 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 = !isMinusOne()
|
public fun C.isNotMinusOne(): Boolean = !isMinusOne()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance of zero constant (zero of the underlying ring).
|
||||||
|
*/
|
||||||
|
public val constantZero: C
|
||||||
|
/**
|
||||||
|
* Instance of unit constant (unit of the underlying ring).
|
||||||
|
*/
|
||||||
|
public val constantOne: C
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Constant-polynomial relation
|
// region Constant-polynomial relation
|
||||||
@ -401,19 +410,12 @@ public interface AbstractPolynomialSpaceOverRing<C, P: AbstractPolynomial<C>, A:
|
|||||||
public override operator fun C.times(other: C): C = ring { this@times * other }
|
public override operator fun C.times(other: C): C = ring { this@times * other }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the instant is zero constant.
|
* Instance of zero constant (zero of the underlying ring).
|
||||||
*/
|
*/
|
||||||
@JvmName("constantIsZero")
|
public override val constantZero: C get() = ring.zero
|
||||||
public override fun C.isZero(): Boolean = ring { this == zero }
|
|
||||||
/**
|
/**
|
||||||
* Check if the instant is unit constant.
|
* Instance of unit constant (unit of the underlying ring).
|
||||||
*/
|
*/
|
||||||
@JvmName("constantIsOne")
|
public override val constantOne: C get() = ring.one
|
||||||
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
|
// endregion
|
||||||
}
|
}
|
@ -190,7 +190,7 @@ public interface AbstractRationalFunctionalSpace<C, P: AbstractPolynomial<C>, R:
|
|||||||
* Check if the instant is zero constant.
|
* Check if the instant is zero constant.
|
||||||
*/
|
*/
|
||||||
@JvmName("constantIsZero")
|
@JvmName("constantIsZero")
|
||||||
public fun C.isZero(): Boolean
|
public fun C.isZero(): Boolean = this == constantZero
|
||||||
/**
|
/**
|
||||||
* Check if the instant is NOT zero constant.
|
* Check if the instant is NOT zero constant.
|
||||||
*/
|
*/
|
||||||
@ -200,7 +200,7 @@ public interface AbstractRationalFunctionalSpace<C, P: AbstractPolynomial<C>, R:
|
|||||||
* Check if the instant is unit constant.
|
* Check if the instant is unit constant.
|
||||||
*/
|
*/
|
||||||
@JvmName("constantIsOne")
|
@JvmName("constantIsOne")
|
||||||
public fun C.isOne(): Boolean
|
public fun C.isOne(): Boolean = this == constantOne
|
||||||
/**
|
/**
|
||||||
* Check if the instant is NOT unit constant.
|
* Check if the instant is NOT unit constant.
|
||||||
*/
|
*/
|
||||||
@ -210,12 +210,21 @@ public interface AbstractRationalFunctionalSpace<C, P: AbstractPolynomial<C>, R:
|
|||||||
* Check if the instant is minus unit constant.
|
* Check if the instant is minus unit constant.
|
||||||
*/
|
*/
|
||||||
@JvmName("constantIsMinusOne")
|
@JvmName("constantIsMinusOne")
|
||||||
public fun C.isMinusOne(): Boolean
|
public fun C.isMinusOne(): Boolean = this == -constantOne
|
||||||
/**
|
/**
|
||||||
* 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 = !isMinusOne()
|
public fun C.isNotMinusOne(): Boolean = !isMinusOne()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance of zero constant (zero of the underlying ring).
|
||||||
|
*/
|
||||||
|
public val constantZero: C
|
||||||
|
/**
|
||||||
|
* Instance of unit constant (unit of the underlying ring).
|
||||||
|
*/
|
||||||
|
public val constantOne: C
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Constant-polynomial relation
|
// region Constant-polynomial relation
|
||||||
@ -399,7 +408,7 @@ 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 equalsTo zero
|
public fun R.isZero(): Boolean = numerator equalsTo polynomialZero
|
||||||
/**
|
/**
|
||||||
* Check if the instant is NOT zero rational function.
|
* Check if the instant is NOT zero rational function.
|
||||||
*/
|
*/
|
||||||
@ -407,7 +416,7 @@ public interface AbstractRationalFunctionalSpace<C, P: AbstractPolynomial<C>, R:
|
|||||||
/**
|
/**
|
||||||
* Check if the instant is unit rational function.
|
* Check if the instant is unit rational function.
|
||||||
*/
|
*/
|
||||||
public fun R.isOne(): Boolean = this equalsTo one
|
public fun R.isOne(): Boolean = numerator equalsTo denominator
|
||||||
/**
|
/**
|
||||||
* Check if the instant is NOT unit rational function.
|
* Check if the instant is NOT unit rational function.
|
||||||
*/
|
*/
|
||||||
@ -415,7 +424,7 @@ public interface AbstractRationalFunctionalSpace<C, P: AbstractPolynomial<C>, R:
|
|||||||
/**
|
/**
|
||||||
* Check if the instant is minus unit rational function.
|
* Check if the instant is minus unit rational function.
|
||||||
*/
|
*/
|
||||||
public fun R.isMinusOne(): Boolean = this equalsTo -one
|
public fun R.isMinusOne(): Boolean = (numerator + denominator).isZero()
|
||||||
/**
|
/**
|
||||||
* Check if the instant is NOT minus unit rational function.
|
* Check if the instant is NOT minus unit rational function.
|
||||||
*/
|
*/
|
||||||
@ -597,35 +606,13 @@ public interface AbstractRationalFunctionalSpaceOverRing<C, P: AbstractPolynomia
|
|||||||
public override operator fun C.times(other: C): C = ring { this@times * other }
|
public override operator fun C.times(other: C): C = ring { this@times * other }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the instant is zero constant.
|
* Instance of zero constant (zero of the underlying ring).
|
||||||
*/
|
*/
|
||||||
@JvmName("constantIsZero")
|
public override val constantZero: C get() = ring.zero
|
||||||
public override fun C.isZero(): Boolean = ring { this@isZero.isZero() }
|
|
||||||
/**
|
/**
|
||||||
* Check if the instant is NOT zero constant.
|
* Instance of unit constant (unit of the underlying ring).
|
||||||
*/
|
*/
|
||||||
@JvmName("constantIsNotZero")
|
public override val constantOne: C get() = ring.one
|
||||||
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
|
// endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -786,6 +773,15 @@ public interface AbstractRationalFunctionalSpaceOverPolynomialSpace<C, P: Abstra
|
|||||||
*/
|
*/
|
||||||
@JvmName("constantIsNotMinusOne")
|
@JvmName("constantIsNotMinusOne")
|
||||||
public override fun C.isNotMinusOne(): Boolean = polynomialRing { this@isNotMinusOne.isNotMinusOne() }
|
public override fun C.isNotMinusOne(): Boolean = polynomialRing { this@isNotMinusOne.isNotMinusOne() }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance of zero constant (zero of the underlying ring).
|
||||||
|
*/
|
||||||
|
public override val constantZero: C get() = polynomialRing.constantZero
|
||||||
|
/**
|
||||||
|
* Instance of unit constant (unit of the underlying ring).
|
||||||
|
*/
|
||||||
|
public override val constantOne: C get() = polynomialRing.constantOne
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Constant-polynomial relation
|
// region Constant-polynomial relation
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.functions
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.*
|
||||||
@ -305,7 +310,7 @@ internal fun Map<Variable, UInt>.cleanUp() = filterValues { it > 0U }
|
|||||||
//fun <C, A: Ring<C>> Variable.asLabeledPolynomial() : LabeledPolynomial<C> = LabeledPolynomial<C>(mapOf(mapOf<Variable, UInt>(this to 1U) to one))
|
//fun <C, A: Ring<C>> Variable.asLabeledPolynomial() : LabeledPolynomial<C> = LabeledPolynomial<C>(mapOf(mapOf<Variable, UInt>(this to 1U) to one))
|
||||||
//
|
//
|
||||||
//context(LabeledPolynomialSpace<C, A>)
|
//context(LabeledPolynomialSpace<C, A>)
|
||||||
//fun <C, A: Ring<C>> Variable.asLabeledPolynomial() : LabeledPolynomial<C> = LabeledPolynomial<C>(mapOf(mapOf<Variable, UInt>(this to 1U) to ring.one))
|
//fun <C, A: Ring<C>> Variable.asLabeledPolynomial() : LabeledPolynomial<C> = LabeledPolynomial<C>(mapOf(mapOf<Variable, UInt>(this to 1U) to constantOne))
|
||||||
//
|
//
|
||||||
//context(A)
|
//context(A)
|
||||||
//fun <C, A: Ring<C>> Variable.asLabeledPolynomial(c: C) : LabeledPolynomial<C> =
|
//fun <C, A: Ring<C>> Variable.asLabeledPolynomial(c: C) : LabeledPolynomial<C> =
|
||||||
@ -328,71 +333,54 @@ internal fun Map<Variable, UInt>.cleanUp() = filterValues { it > 0U }
|
|||||||
*/
|
*/
|
||||||
@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE", "INAPPLICABLE_JVM_NAME")
|
@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE", "INAPPLICABLE_JVM_NAME")
|
||||||
public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
||||||
public val ring: A,
|
public override val ring: A,
|
||||||
) : AbstractPolynomialSpace<C, LabeledPolynomial<C>> {
|
) : AbstractPolynomialSpaceOverRing<C, LabeledPolynomial<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 Variable-integer relation
|
// region Variable-integer relation
|
||||||
public operator fun Variable.plus(other: Int): LabeledPolynomial<C> =
|
public operator fun Variable.plus(other: Int): LabeledPolynomial<C> =
|
||||||
if (other == 0) LabeledPolynomial<C>(mapOf(
|
if (other == 0) LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(this@plus to 1U) to ring.one,
|
mapOf(this@plus to 1U) to constantOne,
|
||||||
))
|
))
|
||||||
else LabeledPolynomial<C>(mapOf(
|
else LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(this@plus to 1U) to ring.one,
|
mapOf(this@plus to 1U) to constantOne,
|
||||||
emptyMap<Variable, UInt>() to ring.one * other,
|
emptyMap<Variable, UInt>() to constantOne * other,
|
||||||
))
|
))
|
||||||
public operator fun Variable.minus(other: Int): LabeledPolynomial<C> =
|
public operator fun Variable.minus(other: Int): LabeledPolynomial<C> =
|
||||||
if (other == 0) LabeledPolynomial<C>(mapOf(
|
if (other == 0) LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(this@minus to 1U) to -ring.one,
|
mapOf(this@minus to 1U) to -constantOne,
|
||||||
))
|
))
|
||||||
else LabeledPolynomial<C>(mapOf(
|
else LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(this@minus to 1U) to -ring.one,
|
mapOf(this@minus to 1U) to -constantOne,
|
||||||
emptyMap<Variable, UInt>() to ring.one * other,
|
emptyMap<Variable, UInt>() to constantOne * other,
|
||||||
))
|
))
|
||||||
public operator fun Variable.times(other: Int): LabeledPolynomial<C> =
|
public operator fun Variable.times(other: Int): LabeledPolynomial<C> =
|
||||||
if (other == 0) zero
|
if (other == 0) zero
|
||||||
else LabeledPolynomial<C>(mapOf(
|
else LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(this to 1U) to ring.one * other,
|
mapOf(this to 1U) to constantOne * other,
|
||||||
))
|
))
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Integer-variable relation
|
// region Integer-variable relation
|
||||||
public operator fun Int.plus(other: Variable): LabeledPolynomial<C> =
|
public operator fun Int.plus(other: Variable): LabeledPolynomial<C> =
|
||||||
if (this == 0) LabeledPolynomial<C>(mapOf(
|
if (this == 0) LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(other to 1U) to ring.one,
|
mapOf(other to 1U) to constantOne,
|
||||||
))
|
))
|
||||||
else LabeledPolynomial<C>(mapOf(
|
else LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(other to 1U) to ring.one,
|
mapOf(other to 1U) to constantOne,
|
||||||
emptyMap<Variable, UInt>() to ring.one * this@plus,
|
emptyMap<Variable, UInt>() to constantOne * this@plus,
|
||||||
))
|
))
|
||||||
public operator fun Int.minus(other: Variable): LabeledPolynomial<C> =
|
public operator fun Int.minus(other: Variable): LabeledPolynomial<C> =
|
||||||
if (this == 0) LabeledPolynomial<C>(mapOf(
|
if (this == 0) LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(other to 1U) to -ring.one,
|
mapOf(other to 1U) to -constantOne,
|
||||||
))
|
))
|
||||||
else LabeledPolynomial<C>(mapOf(
|
else LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(other to 1U) to -ring.one,
|
mapOf(other to 1U) to -constantOne,
|
||||||
emptyMap<Variable, UInt>() to ring.one * this@minus,
|
emptyMap<Variable, UInt>() to constantOne * this@minus,
|
||||||
))
|
))
|
||||||
public operator fun Int.times(other: Variable): LabeledPolynomial<C> =
|
public operator fun Int.times(other: Variable): LabeledPolynomial<C> =
|
||||||
if (this == 0) zero
|
if (this == 0) zero
|
||||||
else LabeledPolynomial<C>(mapOf(
|
else LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(other to 1U) to ring.one * this@times,
|
mapOf(other to 1U) to constantOne * this@times,
|
||||||
))
|
))
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
@ -406,7 +394,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
.apply {
|
.apply {
|
||||||
val degs = emptyMap<Variable, UInt>()
|
val degs = emptyMap<Variable, UInt>()
|
||||||
|
|
||||||
val result = getOrElse(degs) { ring.zero } + other
|
val result = getOrElse(degs) { constantZero } + other
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
if (result.isZero()) remove(degs)
|
||||||
else this[degs] = result
|
else this[degs] = result
|
||||||
@ -421,7 +409,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
.apply {
|
.apply {
|
||||||
val degs = emptyMap<Variable, UInt>()
|
val degs = emptyMap<Variable, UInt>()
|
||||||
|
|
||||||
val result = getOrElse(degs) { ring.zero } - other
|
val result = getOrElse(degs) { constantZero } - other
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
if (result.isZero()) remove(degs)
|
||||||
else this[degs] = result
|
else this[degs] = result
|
||||||
@ -447,7 +435,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
.apply {
|
.apply {
|
||||||
val degs = emptyMap<Variable, UInt>()
|
val degs = emptyMap<Variable, UInt>()
|
||||||
|
|
||||||
val result = this@plus + getOrElse(degs) { ring.zero }
|
val result = this@plus + getOrElse(degs) { constantZero }
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
if (result.isZero()) remove(degs)
|
||||||
else this[degs] = result
|
else this[degs] = result
|
||||||
@ -462,7 +450,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
.apply {
|
.apply {
|
||||||
val degs = emptyMap<Variable, UInt>()
|
val degs = emptyMap<Variable, UInt>()
|
||||||
|
|
||||||
val result = this@minus - getOrElse(degs) { ring.zero }
|
val result = this@minus - getOrElse(degs) { constantZero }
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
if (result.isZero()) remove(degs)
|
||||||
else this[degs] = result
|
else this[degs] = result
|
||||||
@ -478,44 +466,21 @@ public class LabeledPolynomialSpace<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-variable relation
|
// region Constant-variable relation
|
||||||
public operator fun C.plus(other: Variable): LabeledPolynomial<C> =
|
public operator fun C.plus(other: Variable): LabeledPolynomial<C> =
|
||||||
if (isZero()) LabeledPolynomial<C>(mapOf(
|
if (isZero()) LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(other to 1U) to ring.one,
|
mapOf(other to 1U) to constantOne,
|
||||||
))
|
))
|
||||||
else LabeledPolynomial<C>(mapOf(
|
else LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(other to 1U) to ring.one,
|
mapOf(other to 1U) to constantOne,
|
||||||
emptyMap<Variable, UInt>() to this@plus,
|
emptyMap<Variable, UInt>() to this@plus,
|
||||||
))
|
))
|
||||||
public operator fun C.minus(other: Variable): LabeledPolynomial<C> =
|
public operator fun C.minus(other: Variable): LabeledPolynomial<C> =
|
||||||
if (isZero()) LabeledPolynomial<C>(mapOf(
|
if (isZero()) LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(other to 1U) to -ring.one,
|
mapOf(other to 1U) to -constantOne,
|
||||||
))
|
))
|
||||||
else LabeledPolynomial<C>(mapOf(
|
else LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(other to 1U) to -ring.one,
|
mapOf(other to 1U) to -constantOne,
|
||||||
emptyMap<Variable, UInt>() to this@minus,
|
emptyMap<Variable, UInt>() to this@minus,
|
||||||
))
|
))
|
||||||
public operator fun C.times(other: Variable): LabeledPolynomial<C> =
|
public operator fun C.times(other: Variable): LabeledPolynomial<C> =
|
||||||
@ -528,18 +493,18 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
// region Variable-constant relation
|
// region Variable-constant relation
|
||||||
public operator fun Variable.plus(other: C): LabeledPolynomial<C> =
|
public operator fun Variable.plus(other: C): LabeledPolynomial<C> =
|
||||||
if (other.isZero()) LabeledPolynomial<C>(mapOf(
|
if (other.isZero()) LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(this@plus to 1U) to ring.one,
|
mapOf(this@plus to 1U) to constantOne,
|
||||||
))
|
))
|
||||||
else LabeledPolynomial<C>(mapOf(
|
else LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(this@plus to 1U) to ring.one,
|
mapOf(this@plus to 1U) to constantOne,
|
||||||
emptyMap<Variable, UInt>() to other,
|
emptyMap<Variable, UInt>() to other,
|
||||||
))
|
))
|
||||||
public operator fun Variable.minus(other: C): LabeledPolynomial<C> =
|
public operator fun Variable.minus(other: C): LabeledPolynomial<C> =
|
||||||
if (other.isZero()) LabeledPolynomial<C>(mapOf(
|
if (other.isZero()) LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(this@minus to 1U) to -ring.one,
|
mapOf(this@minus to 1U) to -constantOne,
|
||||||
))
|
))
|
||||||
else LabeledPolynomial<C>(mapOf(
|
else LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(this@minus to 1U) to -ring.one,
|
mapOf(this@minus to 1U) to -constantOne,
|
||||||
emptyMap<Variable, UInt>() to other,
|
emptyMap<Variable, UInt>() to other,
|
||||||
))
|
))
|
||||||
public operator fun Variable.times(other: C): LabeledPolynomial<C> =
|
public operator fun Variable.times(other: C): LabeledPolynomial<C> =
|
||||||
@ -559,7 +524,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
.apply {
|
.apply {
|
||||||
val degs = emptyMap<Variable, UInt>()
|
val degs = emptyMap<Variable, UInt>()
|
||||||
|
|
||||||
val result = this@plus + getOrElse(degs) { ring.zero }
|
val result = this@plus + getOrElse(degs) { constantZero }
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
if (result.isZero()) remove(degs)
|
||||||
else this[degs] = result
|
else this[degs] = result
|
||||||
@ -577,7 +542,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
|
|
||||||
val degs = emptyMap<Variable, UInt>()
|
val degs = emptyMap<Variable, UInt>()
|
||||||
|
|
||||||
val result = this@minus - getOrElse(degs) { ring.zero }
|
val result = this@minus - getOrElse(degs) { constantZero }
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
if (result.isZero()) remove(degs)
|
||||||
else this[degs] = result
|
else this[degs] = result
|
||||||
@ -607,7 +572,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
.apply {
|
.apply {
|
||||||
val degs = emptyMap<Variable, UInt>()
|
val degs = emptyMap<Variable, UInt>()
|
||||||
|
|
||||||
val result = getOrElse(degs) { ring.zero } + other
|
val result = getOrElse(degs) { constantZero } + other
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
if (result.isZero()) remove(degs)
|
||||||
else this[degs] = result
|
else this[degs] = result
|
||||||
@ -628,7 +593,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
|
|
||||||
val degs = emptyMap<Variable, UInt>()
|
val degs = emptyMap<Variable, UInt>()
|
||||||
|
|
||||||
val result = getOrElse(degs) { ring.zero } - other
|
val result = getOrElse(degs) { constantZero } - other
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
if (result.isZero()) remove(degs)
|
||||||
else this[degs] = result
|
else this[degs] = result
|
||||||
@ -651,37 +616,37 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
// region Variable-variable relation
|
// region Variable-variable relation
|
||||||
public operator fun Variable.plus(other: Variable): LabeledPolynomial<C> =
|
public operator fun Variable.plus(other: Variable): LabeledPolynomial<C> =
|
||||||
if (this == other) LabeledPolynomial<C>(mapOf(
|
if (this == other) LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(this to 1U) to ring.one * 2
|
mapOf(this to 1U) to constantOne * 2
|
||||||
))
|
))
|
||||||
else LabeledPolynomial<C>(mapOf(
|
else LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(this to 1U) to ring.one,
|
mapOf(this to 1U) to constantOne,
|
||||||
mapOf(other to 1U) to ring.one,
|
mapOf(other to 1U) to constantOne,
|
||||||
))
|
))
|
||||||
public operator fun Variable.minus(other: Variable): LabeledPolynomial<C> =
|
public operator fun Variable.minus(other: Variable): LabeledPolynomial<C> =
|
||||||
if (this == other) zero
|
if (this == other) zero
|
||||||
else LabeledPolynomial<C>(mapOf(
|
else LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(this to 1U) to ring.one,
|
mapOf(this to 1U) to constantOne,
|
||||||
mapOf(other to 1U) to -ring.one,
|
mapOf(other to 1U) to -constantOne,
|
||||||
))
|
))
|
||||||
public operator fun Variable.times(other: Variable): LabeledPolynomial<C> =
|
public operator fun Variable.times(other: Variable): LabeledPolynomial<C> =
|
||||||
if (this == other) LabeledPolynomial<C>(mapOf(
|
if (this == other) LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(this to 2U) to ring.one
|
mapOf(this to 2U) to constantOne
|
||||||
))
|
))
|
||||||
else LabeledPolynomial<C>(mapOf(
|
else LabeledPolynomial<C>(mapOf(
|
||||||
mapOf(this to 1U, other to 1U) to ring.one,
|
mapOf(this to 1U, other to 1U) to constantOne,
|
||||||
))
|
))
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Variable-polynomial relation
|
// region Variable-polynomial relation
|
||||||
public operator fun Variable.plus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
public operator fun Variable.plus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||||
with(other.coefficients) {
|
with(other.coefficients) {
|
||||||
if (isEmpty()) LabeledPolynomial<C>(mapOf(mapOf(this@plus to 1u) to ring.one))
|
if (isEmpty()) LabeledPolynomial<C>(mapOf(mapOf(this@plus to 1u) to constantOne))
|
||||||
else LabeledPolynomial<C>(
|
else LabeledPolynomial<C>(
|
||||||
toMutableMap()
|
toMutableMap()
|
||||||
.apply {
|
.apply {
|
||||||
val degs = mapOf(this@plus to 1U)
|
val degs = mapOf(this@plus to 1U)
|
||||||
|
|
||||||
val result = ring.one + getOrElse(degs) { ring.zero }
|
val result = constantOne + getOrElse(degs) { constantZero }
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
if (result.isZero()) remove(degs)
|
||||||
else this[degs] = result
|
else this[degs] = result
|
||||||
@ -690,7 +655,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
}
|
}
|
||||||
public operator fun Variable.minus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
public operator fun Variable.minus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||||
with(other.coefficients) {
|
with(other.coefficients) {
|
||||||
if (isEmpty()) LabeledPolynomial<C>(mapOf(mapOf(this@minus to 1u) to ring.one))
|
if (isEmpty()) LabeledPolynomial<C>(mapOf(mapOf(this@minus to 1u) to constantOne))
|
||||||
else LabeledPolynomial<C>(
|
else LabeledPolynomial<C>(
|
||||||
toMutableMap()
|
toMutableMap()
|
||||||
.apply {
|
.apply {
|
||||||
@ -698,7 +663,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
|
|
||||||
val degs = mapOf(this@minus to 1U)
|
val degs = mapOf(this@minus to 1U)
|
||||||
|
|
||||||
val result = ring.one - getOrElse(degs) { ring.zero }
|
val result = constantOne - getOrElse(degs) { constantZero }
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
if (result.isZero()) remove(degs)
|
||||||
else this[degs] = result
|
else this[degs] = result
|
||||||
@ -715,13 +680,13 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
// region Polynomial-variable relation
|
// region Polynomial-variable relation
|
||||||
public operator fun LabeledPolynomial<C>.plus(other: Variable): LabeledPolynomial<C> =
|
public operator fun LabeledPolynomial<C>.plus(other: Variable): LabeledPolynomial<C> =
|
||||||
with(coefficients) {
|
with(coefficients) {
|
||||||
if (isEmpty()) LabeledPolynomial<C>(mapOf(mapOf(other to 1u) to ring.one))
|
if (isEmpty()) LabeledPolynomial<C>(mapOf(mapOf(other to 1u) to constantOne))
|
||||||
else LabeledPolynomial<C>(
|
else LabeledPolynomial<C>(
|
||||||
toMutableMap()
|
toMutableMap()
|
||||||
.apply {
|
.apply {
|
||||||
val degs = mapOf(other to 1U)
|
val degs = mapOf(other to 1U)
|
||||||
|
|
||||||
val result = ring.one + getOrElse(degs) { ring.zero }
|
val result = constantOne + getOrElse(degs) { constantZero }
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
if (result.isZero()) remove(degs)
|
||||||
else this[degs] = result
|
else this[degs] = result
|
||||||
@ -730,13 +695,13 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
}
|
}
|
||||||
public operator fun LabeledPolynomial<C>.minus(other: Variable): LabeledPolynomial<C> =
|
public operator fun LabeledPolynomial<C>.minus(other: Variable): LabeledPolynomial<C> =
|
||||||
with(coefficients) {
|
with(coefficients) {
|
||||||
if (isEmpty()) LabeledPolynomial<C>(mapOf(mapOf(other to 1u) to ring.one))
|
if (isEmpty()) LabeledPolynomial<C>(mapOf(mapOf(other to 1u) to constantOne))
|
||||||
else LabeledPolynomial<C>(
|
else LabeledPolynomial<C>(
|
||||||
toMutableMap()
|
toMutableMap()
|
||||||
.apply {
|
.apply {
|
||||||
val degs = mapOf(other to 1U)
|
val degs = mapOf(other to 1U)
|
||||||
|
|
||||||
val result = ring.one - getOrElse(degs) { ring.zero }
|
val result = constantOne - getOrElse(degs) { constantZero }
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
if (result.isZero()) remove(degs)
|
||||||
else this[degs] = result
|
else this[degs] = result
|
||||||
@ -799,8 +764,8 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val zero: LabeledPolynomial<C> = LabeledPolynomial<C>(mapOf(emptyMap<Variable, UInt>() to ring.zero))
|
override val zero: LabeledPolynomial<C> = LabeledPolynomial<C>(mapOf(emptyMap<Variable, UInt>() to constantZero))
|
||||||
override val one: LabeledPolynomial<C> = LabeledPolynomial<C>(mapOf(emptyMap<Variable, UInt>() to ring.one))
|
override val one: LabeledPolynomial<C> = LabeledPolynomial<C>(mapOf(emptyMap<Variable, UInt>() to constantOne))
|
||||||
|
|
||||||
// TODO: Docs
|
// TODO: Docs
|
||||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals")
|
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals")
|
||||||
@ -872,7 +837,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
|
|
||||||
override fun LabeledPolynomial<C>.asConstantOrNull(): C? =
|
override fun LabeledPolynomial<C>.asConstantOrNull(): C? =
|
||||||
with(coefficients) {
|
with(coefficients) {
|
||||||
if(isConstant()) getOrElse(emptyMap()) { ring.zero }
|
if(isConstant()) getOrElse(emptyMap()) { constantZero }
|
||||||
else null
|
else null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,464 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
|
import space.kscience.kmath.operations.Ring
|
||||||
|
import space.kscience.kmath.operations.invoke
|
||||||
|
|
||||||
|
|
||||||
|
public class LabeledRationalFunction<C>(
|
||||||
|
public override val numerator: LabeledPolynomial<C>,
|
||||||
|
public override val denominator: LabeledPolynomial<C>
|
||||||
|
) : AbstractRationalFunction<C, LabeledPolynomial<C>> {
|
||||||
|
override fun toString(): String = "LabeledRationalFunction${numerator.coefficients}/${denominator.coefficients}"
|
||||||
|
}
|
||||||
|
|
||||||
|
// region Internal utilities
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents internal [LabeledRationalFunction] errors.
|
||||||
|
*/
|
||||||
|
internal class LabeledRationalFunctionError : Error {
|
||||||
|
constructor(): super()
|
||||||
|
constructor(message: String): super(message)
|
||||||
|
constructor(message: String?, cause: Throwable?): super(message, cause)
|
||||||
|
constructor(cause: Throwable?): super(cause)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throws an [LabeledRationalFunctionError] with the given [message].
|
||||||
|
*/
|
||||||
|
internal fun labeledRationalFunctionError(message: Any): Nothing = throw LabeledRationalFunctionError(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 } )
|
||||||
|
// )
|
||||||
|
|
||||||
|
// TODO: Rewrite former constructors as fabrics
|
||||||
|
//constructor(numeratorCoefficients: Map<Map<Variable, Int>, C>, denominatorCoefficients: Map<Map<Variable, Int>, C>) : this(
|
||||||
|
//LabeledPolynomial(numeratorCoefficients),
|
||||||
|
//LabeledPolynomial(denominatorCoefficients)
|
||||||
|
//)
|
||||||
|
//
|
||||||
|
//constructor(numeratorCoefficients: Collection<Pair<Map<Variable, Int>, C>>, denominatorCoefficients: Collection<Pair<Map<Variable, Int>, C>>) : this(
|
||||||
|
//LabeledPolynomial(numeratorCoefficients),
|
||||||
|
//LabeledPolynomial(denominatorCoefficients)
|
||||||
|
//)
|
||||||
|
//
|
||||||
|
//constructor(numerator: LabeledPolynomial<C>) : this(numerator, numerator.getOne())
|
||||||
|
//constructor(numeratorCoefficients: Map<Map<Variable, Int>, C>) : this(
|
||||||
|
//LabeledPolynomial(numeratorCoefficients)
|
||||||
|
//)
|
||||||
|
//
|
||||||
|
//constructor(numeratorCoefficients: Collection<Pair<Map<Variable, Int>, C>>) : this(
|
||||||
|
//LabeledPolynomial(numeratorCoefficients)
|
||||||
|
//)
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
public class LabeledRationalFunctionSpace<C, A: Ring<C>>(
|
||||||
|
public val ring: A,
|
||||||
|
) : AbstractRationalFunctionalSpaceOverPolynomialSpace<C, LabeledPolynomial<C>, LabeledRationalFunction<C>, A> {
|
||||||
|
|
||||||
|
override val polynomialRing : LabeledPolynomialSpace<C, A> = LabeledPolynomialSpace(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 LabeledRationalFunction<C>.plus(other: Int): LabeledRationalFunction<C> =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
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 LabeledRationalFunction<C>.minus(other: Int): LabeledRationalFunction<C> =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
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 LabeledRationalFunction<C>.times(other: Int): LabeledRationalFunction<C> =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
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: LabeledRationalFunction<C>): LabeledRationalFunction<C> =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
other.denominator * this + other.numerator,
|
||||||
|
other.denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* 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: LabeledRationalFunction<C>): LabeledRationalFunction<C> =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
other.denominator * this - other.numerator,
|
||||||
|
other.denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* 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: LabeledRationalFunction<C>): LabeledRationalFunction<C> =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
this * other.numerator,
|
||||||
|
other.denominator
|
||||||
|
)
|
||||||
|
// 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: LabeledRationalFunction<C>): LabeledRationalFunction<C> =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
other.denominator * this + other.numerator,
|
||||||
|
other.denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns difference between the constant represented as polynomial and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun C.minus(other: LabeledRationalFunction<C>): LabeledRationalFunction<C> =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
other.denominator * this - other.numerator,
|
||||||
|
other.denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns product of the constant represented as polynomial and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun C.times(other: LabeledRationalFunction<C>): LabeledRationalFunction<C> =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
this * other.numerator,
|
||||||
|
other.denominator
|
||||||
|
)
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Rational-constant relation
|
||||||
|
/**
|
||||||
|
* Returns sum of the constant represented as rational function and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun LabeledRationalFunction<C>.plus(other: C): LabeledRationalFunction<C> =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator + denominator * other,
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns difference between the constant represented as rational function and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun LabeledRationalFunction<C>.minus(other: C): LabeledRationalFunction<C> =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator - denominator * other,
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns product of the constant represented as rational function and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun LabeledRationalFunction<C>.times(other: C): LabeledRationalFunction<C> =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
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 LabeledPolynomial<C>.plus(other: LabeledRationalFunction<C>): LabeledRationalFunction<C> =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
other.denominator * this + other.numerator,
|
||||||
|
other.denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns difference between the polynomial represented as polynomial and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun LabeledPolynomial<C>.minus(other: LabeledRationalFunction<C>): LabeledRationalFunction<C> =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
other.denominator * this - other.numerator,
|
||||||
|
other.denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns product of the polynomial represented as polynomial and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun LabeledPolynomial<C>.times(other: LabeledRationalFunction<C>): LabeledRationalFunction<C> =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
this * other.numerator,
|
||||||
|
other.denominator
|
||||||
|
)
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Rational-polynomial relation
|
||||||
|
/**
|
||||||
|
* Returns sum of the polynomial represented as rational function and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun LabeledRationalFunction<C>.plus(other: LabeledPolynomial<C>): LabeledRationalFunction<C> =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator + denominator * other,
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns difference between the polynomial represented as rational function and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun LabeledRationalFunction<C>.minus(other: LabeledPolynomial<C>): LabeledRationalFunction<C> =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator - denominator * other,
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns product of the polynomial represented as rational function and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun LabeledRationalFunction<C>.times(other: LabeledPolynomial<C>): LabeledRationalFunction<C> =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator * other,
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Rational-rational relation
|
||||||
|
/**
|
||||||
|
* Returns negation of the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun LabeledRationalFunction<C>.unaryMinus(): LabeledRationalFunction<C> = LabeledRationalFunction(-numerator, denominator)
|
||||||
|
/**
|
||||||
|
* Returns sum of the rational functions.
|
||||||
|
*/
|
||||||
|
public override operator fun LabeledRationalFunction<C>.plus(other: LabeledRationalFunction<C>): LabeledRationalFunction<C> =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator * other.denominator + denominator * other.numerator,
|
||||||
|
denominator * other.denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns difference of the rational functions.
|
||||||
|
*/
|
||||||
|
public override operator fun LabeledRationalFunction<C>.minus(other: LabeledRationalFunction<C>): LabeledRationalFunction<C> =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator * other.denominator - denominator * other.numerator,
|
||||||
|
denominator * other.denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns product of the rational functions.
|
||||||
|
*/
|
||||||
|
public override operator fun LabeledRationalFunction<C>.times(other: LabeledRationalFunction<C>): LabeledRationalFunction<C> =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator * other.numerator,
|
||||||
|
denominator * other.denominator
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance of zero rational function (zero of the rational functions ring).
|
||||||
|
*/
|
||||||
|
public override val zero: LabeledRationalFunction<C> = LabeledRationalFunction(polynomialZero, polynomialOne)
|
||||||
|
/**
|
||||||
|
* Instance of unit polynomial (unit of the rational functions ring).
|
||||||
|
*/
|
||||||
|
public override val one: LabeledRationalFunction<C> = LabeledRationalFunction(polynomialOne, polynomialOne)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks equality of the rational functions.
|
||||||
|
*/
|
||||||
|
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals")
|
||||||
|
public override infix fun LabeledRationalFunction<C>.equalsTo(other: LabeledRationalFunction<C>): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
|
||||||
|
if ( !(numerator.isZero() xor 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
|
||||||
|
}
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Polynomial properties
|
||||||
|
/**
|
||||||
|
* Map that associates variables (that appear in the polynomial in positive exponents) with their most exponents
|
||||||
|
* in which they are appeared in the polynomial.
|
||||||
|
*
|
||||||
|
* As consequence all values in the map are positive integers. Also, if the polynomial is constant, the map is empty.
|
||||||
|
* And keys of the map is the same as in [variables].
|
||||||
|
*/
|
||||||
|
public val LabeledPolynomial<C>.degrees: Map<Variable, UInt> get() = polynomialRing { degrees }
|
||||||
|
/**
|
||||||
|
* Set of all variables that appear in the polynomial in positive exponents.
|
||||||
|
*/
|
||||||
|
public val LabeledPolynomial<C>.variables: Set<Variable> get() = polynomialRing { variables }
|
||||||
|
/**
|
||||||
|
* Count of all variables that appear in the polynomial in positive exponents.
|
||||||
|
*/
|
||||||
|
public val LabeledPolynomial<C>.countOfVariables: Int get() = polynomialRing { countOfVariables }
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Rational properties
|
||||||
|
/**
|
||||||
|
* Count of all variables that appear in the polynomial in positive exponents.
|
||||||
|
*/
|
||||||
|
public val LabeledRationalFunction<C>.variables: Set<Variable>
|
||||||
|
get() = numerator.variables union denominator.variables
|
||||||
|
/**
|
||||||
|
* Count of all variables that appear in the polynomial in positive exponents.
|
||||||
|
*/
|
||||||
|
public val LabeledRationalFunction<C>.countOfVariables: Int get() = variables.size
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region REST TODO: Разобрать
|
||||||
|
|
||||||
|
public operator fun LabeledRationalFunction<C>.div(other: LabeledRationalFunction<C>): LabeledRationalFunction<C> =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator * other.denominator,
|
||||||
|
denominator * other.numerator
|
||||||
|
)
|
||||||
|
|
||||||
|
public operator fun LabeledRationalFunction<C>.div(other: LabeledPolynomial<C>): LabeledRationalFunction<C> =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator,
|
||||||
|
denominator * other
|
||||||
|
)
|
||||||
|
|
||||||
|
public operator fun LabeledRationalFunction<C>.div(other: C): LabeledRationalFunction<C> =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator,
|
||||||
|
denominator * other
|
||||||
|
)
|
||||||
|
|
||||||
|
// operator fun invoke(arg: Map<Variable, C>): LabeledRationalFunction<C> =
|
||||||
|
// LabeledRationalFunction(
|
||||||
|
// numerator(arg),
|
||||||
|
// denominator(arg)
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// @JvmName("invokeLabeledPolynomial")
|
||||||
|
// operator fun invoke(arg: Map<Variable, LabeledPolynomial<C>>): LabeledRationalFunction<C> =
|
||||||
|
// LabeledRationalFunction(
|
||||||
|
// numerator(arg),
|
||||||
|
// denominator(arg)
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// @JvmName("invokeLabeledRationalFunction")
|
||||||
|
// operator fun invoke(arg: Map<Variable, LabeledRationalFunction<C>>): LabeledRationalFunction<C> {
|
||||||
|
// var num = numerator invokeRFTakeNumerator arg
|
||||||
|
// var den = denominator invokeRFTakeNumerator arg
|
||||||
|
// for (variable in variables) if (variable in arg) {
|
||||||
|
// val degreeDif = degrees[variable]!!
|
||||||
|
// if (degreeDif > 0)
|
||||||
|
// den = multiplyByPower(den, arg[variable]!!.denominator, degreeDif)
|
||||||
|
// else
|
||||||
|
// num = multiplyByPower(num, arg[variable]!!.denominator, -degreeDif)
|
||||||
|
// }
|
||||||
|
// return LabeledRationalFunction(num, den)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun toString(): String = toString(emptyMap())
|
||||||
|
//
|
||||||
|
// fun toString(names: Map<Variable, String> = emptyMap()): String =
|
||||||
|
// when (true) {
|
||||||
|
// numerator.isZero() -> "0"
|
||||||
|
// denominator.isOne() -> numerator.toString(names)
|
||||||
|
// else -> "${numerator.toStringWithBrackets(names)}/${denominator.toStringWithBrackets(names)}"
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun toString(namer: (Variable) -> String): String =
|
||||||
|
// when (true) {
|
||||||
|
// numerator.isZero() -> "0"
|
||||||
|
// denominator.isOne() -> numerator.toString(namer)
|
||||||
|
// else -> "${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)}"
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun toStringWithBrackets(names: Map<Variable, String> = emptyMap()): String =
|
||||||
|
// when (true) {
|
||||||
|
// numerator.isZero() -> "0"
|
||||||
|
// denominator.isOne() -> numerator.toStringWithBrackets(names)
|
||||||
|
// else -> "(${numerator.toStringWithBrackets(names)}/${denominator.toStringWithBrackets(names)})"
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun toStringWithBrackets(namer: (Variable) -> String): String =
|
||||||
|
// when (true) {
|
||||||
|
// numerator.isZero() -> "0"
|
||||||
|
// denominator.isOne() -> numerator.toStringWithBrackets(namer)
|
||||||
|
// else -> "(${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)})"
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun toReversedString(names: Map<Variable, String> = emptyMap()): String =
|
||||||
|
// when (true) {
|
||||||
|
// numerator.isZero() -> "0"
|
||||||
|
// denominator.isOne() -> numerator.toReversedString(names)
|
||||||
|
// else -> "${numerator.toReversedStringWithBrackets(names)}/${denominator.toReversedStringWithBrackets(names)}"
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun toReversedString(namer: (Variable) -> String): String =
|
||||||
|
// when (true) {
|
||||||
|
// numerator.isZero() -> "0"
|
||||||
|
// denominator.isOne() -> numerator.toReversedString(namer)
|
||||||
|
// else -> "${numerator.toReversedStringWithBrackets(namer)}/${denominator.toReversedStringWithBrackets(namer)}"
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun toReversedStringWithBrackets(names: Map<Variable, String> = emptyMap()): String =
|
||||||
|
// when (true) {
|
||||||
|
// numerator.isZero() -> "0"
|
||||||
|
// denominator.isOne() -> numerator.toReversedStringWithBrackets(names)
|
||||||
|
// else -> "(${numerator.toReversedStringWithBrackets(names)}/${denominator.toReversedStringWithBrackets(names)})"
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun toReversedStringWithBrackets(namer: (Variable) -> String): String =
|
||||||
|
// when (true) {
|
||||||
|
// numerator.isZero() -> "0"
|
||||||
|
// denominator.isOne() -> numerator.toReversedStringWithBrackets(namer)
|
||||||
|
// else -> "(${numerator.toReversedStringWithBrackets(namer)}/${denominator.toReversedStringWithBrackets(namer)})"
|
||||||
|
// }
|
||||||
|
}
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.functions
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.*
|
||||||
@ -272,7 +277,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
.apply {
|
.apply {
|
||||||
val degs = emptyList<UInt>()
|
val degs = emptyList<UInt>()
|
||||||
|
|
||||||
val result = getOrElse(degs) { ring.zero } + other
|
val result = getOrElse(degs) { constantZero } + other
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
if (result.isZero()) remove(degs)
|
||||||
else this[degs] = result
|
else this[degs] = result
|
||||||
@ -287,7 +292,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
.apply {
|
.apply {
|
||||||
val degs = emptyList<UInt>()
|
val degs = emptyList<UInt>()
|
||||||
|
|
||||||
val result = getOrElse(degs) { ring.zero } - other
|
val result = getOrElse(degs) { constantZero } - other
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
if (result.isZero()) remove(degs)
|
||||||
else this[degs] = result
|
else this[degs] = result
|
||||||
@ -313,7 +318,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
.apply {
|
.apply {
|
||||||
val degs = emptyList<UInt>()
|
val degs = emptyList<UInt>()
|
||||||
|
|
||||||
val result = this@plus + getOrElse(degs) { ring.zero }
|
val result = this@plus + getOrElse(degs) { constantZero }
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
if (result.isZero()) remove(degs)
|
||||||
else this[degs] = result
|
else this[degs] = result
|
||||||
@ -328,7 +333,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
.apply {
|
.apply {
|
||||||
val degs = emptyList<UInt>()
|
val degs = emptyList<UInt>()
|
||||||
|
|
||||||
val result = this@minus - getOrElse(degs) { ring.zero }
|
val result = this@minus - getOrElse(degs) { constantZero }
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
if (result.isZero()) remove(degs)
|
||||||
else this[degs] = result
|
else this[degs] = result
|
||||||
@ -354,7 +359,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
.apply {
|
.apply {
|
||||||
val degs = emptyList<UInt>()
|
val degs = emptyList<UInt>()
|
||||||
|
|
||||||
val result = this@plus + getOrElse(degs) { ring.zero }
|
val result = this@plus + getOrElse(degs) { constantZero }
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
if (result.isZero()) remove(degs)
|
||||||
else this[degs] = result
|
else this[degs] = result
|
||||||
@ -372,7 +377,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
|
|
||||||
val degs = emptyList<UInt>()
|
val degs = emptyList<UInt>()
|
||||||
|
|
||||||
val result = this@minus - getOrElse(degs) { ring.zero }
|
val result = this@minus - getOrElse(degs) { constantZero }
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
if (result.isZero()) remove(degs)
|
||||||
else this[degs] = result
|
else this[degs] = result
|
||||||
@ -402,7 +407,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
.apply {
|
.apply {
|
||||||
val degs = emptyList<UInt>()
|
val degs = emptyList<UInt>()
|
||||||
|
|
||||||
val result = getOrElse(degs) { ring.zero } + other
|
val result = getOrElse(degs) { constantZero } + other
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
if (result.isZero()) remove(degs)
|
||||||
else this[degs] = result
|
else this[degs] = result
|
||||||
@ -421,7 +426,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
.apply {
|
.apply {
|
||||||
val degs = emptyList<UInt>()
|
val degs = emptyList<UInt>()
|
||||||
|
|
||||||
val result = getOrElse(degs) { ring.zero } - other
|
val result = getOrElse(degs) { constantZero } - other
|
||||||
|
|
||||||
if (result.isZero()) remove(degs)
|
if (result.isZero()) remove(degs)
|
||||||
else this[degs] = result
|
else this[degs] = result
|
||||||
@ -522,7 +527,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
override val one: NumberedPolynomial<C> =
|
override val one: NumberedPolynomial<C> =
|
||||||
NumberedPolynomial<C>(
|
NumberedPolynomial<C>(
|
||||||
mapOf(
|
mapOf(
|
||||||
listOf<UInt>() to ring.one // 1 * x_1^0 * x_2^0 * ...
|
listOf<UInt>() to constantOne // 1 * x_1^0 * x_2^0 * ...
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -538,6 +543,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
|
|
||||||
// Not sure is it necessary...
|
// Not sure is it necessary...
|
||||||
// region Polynomial properties
|
// region Polynomial properties
|
||||||
|
// TODO: Replace `countOfVariables` with `lastVariable` and create new `countOfVariables`
|
||||||
/**
|
/**
|
||||||
* Count of all variables that appear in the polynomial in positive exponents.
|
* Count of all variables that appear in the polynomial in positive exponents.
|
||||||
*/
|
*/
|
||||||
@ -590,7 +596,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
|
|
||||||
override fun NumberedPolynomial<C>.asConstantOrNull(): C? =
|
override fun NumberedPolynomial<C>.asConstantOrNull(): C? =
|
||||||
with(coefficients) {
|
with(coefficients) {
|
||||||
if(isConstant()) getOrElse(emptyList()) { ring.zero }
|
if(isConstant()) getOrElse(emptyList()) { constantZero }
|
||||||
else null
|
else null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,453 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
|
import space.kscience.kmath.operations.*
|
||||||
|
import kotlin.math.max
|
||||||
|
|
||||||
|
|
||||||
|
public class NumberedRationalFunction<C> internal constructor(
|
||||||
|
public override val numerator: NumberedPolynomial<C>,
|
||||||
|
public override val denominator: NumberedPolynomial<C>
|
||||||
|
) : AbstractRationalFunction<C, NumberedPolynomial<C>> {
|
||||||
|
override fun toString(): String = "NumberedRationalFunction${numerator.coefficients}/${denominator.coefficients}"
|
||||||
|
}
|
||||||
|
|
||||||
|
// region Internal utilities
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents internal [NumberedRationalFunction] errors.
|
||||||
|
*/
|
||||||
|
internal class NumberedRationalFunctionError : Error {
|
||||||
|
constructor(): super()
|
||||||
|
constructor(message: String): super(message)
|
||||||
|
constructor(message: String?, cause: Throwable?): super(message, cause)
|
||||||
|
constructor(cause: Throwable?): super(cause)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throws an [NumberedRationalFunctionError] with the given [message].
|
||||||
|
*/
|
||||||
|
internal fun numberedRationalFunctionError(message: Any): Nothing = throw NumberedRationalFunctionError(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 } )
|
||||||
|
// )
|
||||||
|
|
||||||
|
// TODO: Rewrite former constructors as fabrics
|
||||||
|
//constructor(numeratorCoefficients: Map<List<Int>, C>, denominatorCoefficients: Map<List<Int>, C>) : this(
|
||||||
|
//Polynomial(numeratorCoefficients),
|
||||||
|
//Polynomial(denominatorCoefficients)
|
||||||
|
//)
|
||||||
|
//constructor(numeratorCoefficients: Collection<Pair<List<Int>, C>>, denominatorCoefficients: Collection<Pair<List<Int>, C>>) : this(
|
||||||
|
//Polynomial(numeratorCoefficients),
|
||||||
|
//Polynomial(denominatorCoefficients)
|
||||||
|
//)
|
||||||
|
//constructor(numerator: Polynomial<C>) : this(numerator, numerator.getOne())
|
||||||
|
//constructor(numeratorCoefficients: Map<List<Int>, C>) : this(
|
||||||
|
//Polynomial(numeratorCoefficients)
|
||||||
|
//)
|
||||||
|
//constructor(numeratorCoefficients: Collection<Pair<List<Int>, C>>) : this(
|
||||||
|
//Polynomial(numeratorCoefficients)
|
||||||
|
//)
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
public class NumberedRationalFunctionSpace<C, A: Ring<C>> (
|
||||||
|
public val ring: A,
|
||||||
|
) : AbstractRationalFunctionalSpaceOverPolynomialSpace<C, NumberedPolynomial<C>, NumberedRationalFunction<C>, A> {
|
||||||
|
|
||||||
|
override val polynomialRing : NumberedPolynomialSpace<C, A> = NumberedPolynomialSpace(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 NumberedRationalFunction<C>.plus(other: Int): NumberedRationalFunction<C> =
|
||||||
|
NumberedRationalFunction(
|
||||||
|
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 NumberedRationalFunction<C>.minus(other: Int): NumberedRationalFunction<C> =
|
||||||
|
NumberedRationalFunction(
|
||||||
|
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 NumberedRationalFunction<C>.times(other: Int): NumberedRationalFunction<C> =
|
||||||
|
NumberedRationalFunction(
|
||||||
|
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: NumberedRationalFunction<C>): NumberedRationalFunction<C> =
|
||||||
|
NumberedRationalFunction(
|
||||||
|
other.denominator * this + other.numerator,
|
||||||
|
other.denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* 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: NumberedRationalFunction<C>): NumberedRationalFunction<C> =
|
||||||
|
NumberedRationalFunction(
|
||||||
|
other.denominator * this - other.numerator,
|
||||||
|
other.denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* 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: NumberedRationalFunction<C>): NumberedRationalFunction<C> =
|
||||||
|
NumberedRationalFunction(
|
||||||
|
this * other.numerator,
|
||||||
|
other.denominator
|
||||||
|
)
|
||||||
|
// 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: NumberedRationalFunction<C>): NumberedRationalFunction<C> =
|
||||||
|
NumberedRationalFunction(
|
||||||
|
other.denominator * this + other.numerator,
|
||||||
|
other.denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns difference between the constant represented as polynomial and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun C.minus(other: NumberedRationalFunction<C>): NumberedRationalFunction<C> =
|
||||||
|
NumberedRationalFunction(
|
||||||
|
other.denominator * this - other.numerator,
|
||||||
|
other.denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns product of the constant represented as polynomial and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun C.times(other: NumberedRationalFunction<C>): NumberedRationalFunction<C> =
|
||||||
|
NumberedRationalFunction(
|
||||||
|
this * other.numerator,
|
||||||
|
other.denominator
|
||||||
|
)
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Rational-constant relation
|
||||||
|
/**
|
||||||
|
* Returns sum of the constant represented as rational function and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun NumberedRationalFunction<C>.plus(other: C): NumberedRationalFunction<C> =
|
||||||
|
NumberedRationalFunction(
|
||||||
|
numerator + denominator * other,
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns difference between the constant represented as rational function and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun NumberedRationalFunction<C>.minus(other: C): NumberedRationalFunction<C> =
|
||||||
|
NumberedRationalFunction(
|
||||||
|
numerator - denominator * other,
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns product of the constant represented as rational function and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun NumberedRationalFunction<C>.times(other: C): NumberedRationalFunction<C> =
|
||||||
|
NumberedRationalFunction(
|
||||||
|
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 NumberedPolynomial<C>.plus(other: NumberedRationalFunction<C>): NumberedRationalFunction<C> =
|
||||||
|
NumberedRationalFunction(
|
||||||
|
other.denominator * this + other.numerator,
|
||||||
|
other.denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns difference between the polynomial represented as polynomial and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun NumberedPolynomial<C>.minus(other: NumberedRationalFunction<C>): NumberedRationalFunction<C> =
|
||||||
|
NumberedRationalFunction(
|
||||||
|
other.denominator * this - other.numerator,
|
||||||
|
other.denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns product of the polynomial represented as polynomial and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun NumberedPolynomial<C>.times(other: NumberedRationalFunction<C>): NumberedRationalFunction<C> =
|
||||||
|
NumberedRationalFunction(
|
||||||
|
this * other.numerator,
|
||||||
|
other.denominator
|
||||||
|
)
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Rational-polynomial relation
|
||||||
|
/**
|
||||||
|
* Returns sum of the polynomial represented as rational function and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun NumberedRationalFunction<C>.plus(other: NumberedPolynomial<C>): NumberedRationalFunction<C> =
|
||||||
|
NumberedRationalFunction(
|
||||||
|
numerator + denominator * other,
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns difference between the polynomial represented as rational function and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun NumberedRationalFunction<C>.minus(other: NumberedPolynomial<C>): NumberedRationalFunction<C> =
|
||||||
|
NumberedRationalFunction(
|
||||||
|
numerator - denominator * other,
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns product of the polynomial represented as rational function and the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun NumberedRationalFunction<C>.times(other: NumberedPolynomial<C>): NumberedRationalFunction<C> =
|
||||||
|
NumberedRationalFunction(
|
||||||
|
numerator * other,
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Rational-rational relation
|
||||||
|
/**
|
||||||
|
* Returns negation of the rational function.
|
||||||
|
*/
|
||||||
|
public override operator fun NumberedRationalFunction<C>.unaryMinus(): NumberedRationalFunction<C> = NumberedRationalFunction(-numerator, denominator)
|
||||||
|
/**
|
||||||
|
* Returns sum of the rational functions.
|
||||||
|
*/
|
||||||
|
public override operator fun NumberedRationalFunction<C>.plus(other: NumberedRationalFunction<C>): NumberedRationalFunction<C> =
|
||||||
|
NumberedRationalFunction(
|
||||||
|
numerator * other.denominator + denominator * other.numerator,
|
||||||
|
denominator * other.denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns difference of the rational functions.
|
||||||
|
*/
|
||||||
|
public override operator fun NumberedRationalFunction<C>.minus(other: NumberedRationalFunction<C>): NumberedRationalFunction<C> =
|
||||||
|
NumberedRationalFunction(
|
||||||
|
numerator * other.denominator - denominator * other.numerator,
|
||||||
|
denominator * other.denominator
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* Returns product of the rational functions.
|
||||||
|
*/
|
||||||
|
public override operator fun NumberedRationalFunction<C>.times(other: NumberedRationalFunction<C>): NumberedRationalFunction<C> =
|
||||||
|
NumberedRationalFunction(
|
||||||
|
numerator * other.numerator,
|
||||||
|
denominator * other.denominator
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance of zero rational function (zero of the rational functions ring).
|
||||||
|
*/
|
||||||
|
public override val zero: NumberedRationalFunction<C> = NumberedRationalFunction(polynomialZero, polynomialOne)
|
||||||
|
/**
|
||||||
|
* Instance of unit polynomial (unit of the rational functions ring).
|
||||||
|
*/
|
||||||
|
public override val one: NumberedRationalFunction<C> = NumberedRationalFunction(polynomialOne, polynomialOne)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks equality of the rational functions.
|
||||||
|
*/
|
||||||
|
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals")
|
||||||
|
public override infix fun NumberedRationalFunction<C>.equalsTo(other: NumberedRationalFunction<C>): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
|
||||||
|
if ( !(numerator.isZero() xor other.numerator.isZero()) ) return false
|
||||||
|
|
||||||
|
val countOfVariables = max(this.countOfVariables, other.countOfVariables)
|
||||||
|
val thisNumeratorDegrees = this.numerator.degrees
|
||||||
|
val thisDenominatorDegrees = this.denominator.degrees
|
||||||
|
val otherNumeratorDegrees = other.numerator.degrees
|
||||||
|
val otherDenominatorDegrees = other.denominator.degrees
|
||||||
|
for (variable in 0 until 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
|
||||||
|
}
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Polynomial properties
|
||||||
|
/**
|
||||||
|
* Count of all variables that appear in the polynomial in positive exponents.
|
||||||
|
*/
|
||||||
|
public val NumberedPolynomial<C>.countOfVariables: Int get() = polynomialRing { countOfVariables }
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* As consequence all values in the list are non-negative integers. Also, if the polynomial is constant, the list is empty.
|
||||||
|
* And size of the list is [countOfVariables].
|
||||||
|
*/
|
||||||
|
public val NumberedPolynomial<C>.degrees: List<UInt> get() = polynomialRing { degrees }
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Rational properties
|
||||||
|
/**
|
||||||
|
* Count of all variables that appear in the polynomial in positive exponents.
|
||||||
|
*/
|
||||||
|
public val NumberedRationalFunction<C>.countOfVariables: Int
|
||||||
|
get() = polynomialRing { max(numerator.countOfVariables, denominator.countOfVariables) }
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region REST TODO: Разобрать
|
||||||
|
|
||||||
|
public operator fun NumberedRationalFunction<C>.div(other: NumberedRationalFunction<C>): NumberedRationalFunction<C> =
|
||||||
|
NumberedRationalFunction(
|
||||||
|
numerator * other.denominator,
|
||||||
|
denominator * other.numerator
|
||||||
|
)
|
||||||
|
|
||||||
|
public operator fun NumberedRationalFunction<C>.div(other: NumberedPolynomial<C>): NumberedRationalFunction<C> =
|
||||||
|
NumberedRationalFunction(
|
||||||
|
numerator,
|
||||||
|
denominator * other
|
||||||
|
)
|
||||||
|
|
||||||
|
public operator fun NumberedRationalFunction<C>.div(other: C): NumberedRationalFunction<C> =
|
||||||
|
NumberedRationalFunction(
|
||||||
|
numerator,
|
||||||
|
denominator * other
|
||||||
|
)
|
||||||
|
|
||||||
|
// operator fun invoke(arg: Map<Int, C>): NumberedRationalFunction<C> =
|
||||||
|
// NumberedRationalFunction(
|
||||||
|
// numerator(arg),
|
||||||
|
// denominator(arg)
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// @JvmName("invokePolynomial")
|
||||||
|
// operator fun invoke(arg: Map<Int, Polynomial<C>>): NumberedRationalFunction<C> =
|
||||||
|
// NumberedRationalFunction(
|
||||||
|
// numerator(arg),
|
||||||
|
// denominator(arg)
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// @JvmName("invokeRationalFunction")
|
||||||
|
// operator fun invoke(arg: Map<Int, NumberedRationalFunction<C>>): NumberedRationalFunction<C> {
|
||||||
|
// var num = numerator invokeRFTakeNumerator arg
|
||||||
|
// var den = denominator invokeRFTakeNumerator arg
|
||||||
|
// for (variable in 0 until max(numerator.countOfVariables, denominator.countOfVariables)) if (variable in arg) {
|
||||||
|
// val degreeDif = numerator.degrees.getOrElse(variable) { 0 } - denominator.degrees.getOrElse(variable) { 0 }
|
||||||
|
// if (degreeDif > 0)
|
||||||
|
// den = multiplyByPower(den, arg[variable]!!.denominator, degreeDif)
|
||||||
|
// else
|
||||||
|
// num = multiplyByPower(num, arg[variable]!!.denominator, -degreeDif)
|
||||||
|
// }
|
||||||
|
// return NumberedRationalFunction(num, den)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun toString(): String = toString(Polynomial.variableName)
|
||||||
|
//
|
||||||
|
// fun toString(withVariableName: String = Polynomial.variableName): String =
|
||||||
|
// when(true) {
|
||||||
|
// numerator.isZero() -> "0"
|
||||||
|
// denominator.isOne() -> numerator.toString(withVariableName)
|
||||||
|
// else -> "${numerator.toStringWithBrackets(withVariableName)}/${denominator.toStringWithBrackets(withVariableName)}"
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun toString(namer: (Int) -> String): String =
|
||||||
|
// when(true) {
|
||||||
|
// numerator.isZero() -> "0"
|
||||||
|
// denominator.isOne() -> numerator.toString(namer)
|
||||||
|
// else -> "${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)}"
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun toStringWithBrackets(withVariableName: String = Polynomial.variableName): String =
|
||||||
|
// when(true) {
|
||||||
|
// numerator.isZero() -> "0"
|
||||||
|
// denominator.isOne() -> numerator.toStringWithBrackets(withVariableName)
|
||||||
|
// else -> "(${numerator.toStringWithBrackets(withVariableName)}/${denominator.toStringWithBrackets(withVariableName)})"
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun toStringWithBrackets(namer: (Int) -> String): String =
|
||||||
|
// when(true) {
|
||||||
|
// numerator.isZero() -> "0"
|
||||||
|
// denominator.isOne() -> numerator.toStringWithBrackets(namer)
|
||||||
|
// else -> "(${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)})"
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun toReversedString(withVariableName: String = Polynomial.variableName): String =
|
||||||
|
// when(true) {
|
||||||
|
// numerator.isZero() -> "0"
|
||||||
|
// denominator.isOne() -> numerator.toReversedString(withVariableName)
|
||||||
|
// else -> "${numerator.toReversedStringWithBrackets(withVariableName)}/${denominator.toReversedStringWithBrackets(withVariableName)}"
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun toReversedString(namer: (Int) -> String): String =
|
||||||
|
// when(true) {
|
||||||
|
// numerator.isZero() -> "0"
|
||||||
|
// denominator.isOne() -> numerator.toReversedString(namer)
|
||||||
|
// else -> "${numerator.toReversedStringWithBrackets(namer)}/${denominator.toReversedStringWithBrackets(namer)}"
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun toReversedStringWithBrackets(withVariableName: String = Polynomial.variableName): String =
|
||||||
|
// when(true) {
|
||||||
|
// numerator.isZero() -> "0"
|
||||||
|
// denominator.isOne() -> numerator.toReversedStringWithBrackets(withVariableName)
|
||||||
|
// else -> "(${numerator.toReversedStringWithBrackets(withVariableName)}/${denominator.toReversedStringWithBrackets(withVariableName)})"
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun toReversedStringWithBrackets(namer: (Int) -> String): String =
|
||||||
|
// when(true) {
|
||||||
|
// numerator.isZero() -> "0"
|
||||||
|
// denominator.isOne() -> numerator.toReversedStringWithBrackets(namer)
|
||||||
|
// else -> "(${numerator.toReversedStringWithBrackets(namer)}/${denominator.toReversedStringWithBrackets(namer)})"
|
||||||
|
// }
|
||||||
|
}
|
@ -80,7 +80,7 @@ public open class PolynomialSpace<C, A : Ring<C>>(
|
|||||||
coefficients
|
coefficients
|
||||||
.toMutableList()
|
.toMutableList()
|
||||||
.apply {
|
.apply {
|
||||||
val result = getOrElse(0) { ring.zero } + other
|
val result = getOrElse(0) { constantZero } + other
|
||||||
val isResultZero = result.isZero()
|
val isResultZero = result.isZero()
|
||||||
|
|
||||||
when {
|
when {
|
||||||
@ -97,7 +97,7 @@ public open class PolynomialSpace<C, A : Ring<C>>(
|
|||||||
coefficients
|
coefficients
|
||||||
.toMutableList()
|
.toMutableList()
|
||||||
.apply {
|
.apply {
|
||||||
val result = getOrElse(0) { ring.zero } - other
|
val result = getOrElse(0) { constantZero } - other
|
||||||
val isResultZero = result.isZero()
|
val isResultZero = result.isZero()
|
||||||
|
|
||||||
when {
|
when {
|
||||||
@ -124,7 +124,7 @@ public open class PolynomialSpace<C, A : Ring<C>>(
|
|||||||
other.coefficients
|
other.coefficients
|
||||||
.toMutableList()
|
.toMutableList()
|
||||||
.apply {
|
.apply {
|
||||||
val result = this@plus + getOrElse(0) { ring.zero }
|
val result = this@plus + getOrElse(0) { constantZero }
|
||||||
val isResultZero = result.isZero()
|
val isResultZero = result.isZero()
|
||||||
|
|
||||||
when {
|
when {
|
||||||
@ -143,7 +143,7 @@ public open class PolynomialSpace<C, A : Ring<C>>(
|
|||||||
.apply {
|
.apply {
|
||||||
forEachIndexed { index, c -> if (index != 0) this[index] = -c }
|
forEachIndexed { index, c -> if (index != 0) this[index] = -c }
|
||||||
|
|
||||||
val result = this@minus - getOrElse(0) { ring.zero }
|
val result = this@minus - getOrElse(0) { constantZero }
|
||||||
val isResultZero = result.isZero()
|
val isResultZero = result.isZero()
|
||||||
|
|
||||||
when {
|
when {
|
||||||
@ -281,7 +281,7 @@ public open class PolynomialSpace<C, A : Ring<C>>(
|
|||||||
else -> coefficients[it] + other.coefficients[it]
|
else -> coefficients[it] + other.coefficients[it]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.ifEmpty { listOf(ring.zero) }
|
.ifEmpty { listOf(constantZero) }
|
||||||
)
|
)
|
||||||
public override operator fun Polynomial<C>.minus(other: Polynomial<C>): Polynomial<C> =
|
public override operator fun Polynomial<C>.minus(other: Polynomial<C>): Polynomial<C> =
|
||||||
Polynomial(
|
Polynomial(
|
||||||
@ -293,7 +293,7 @@ public open class PolynomialSpace<C, A : Ring<C>>(
|
|||||||
else -> coefficients[it] - other.coefficients[it]
|
else -> coefficients[it] - other.coefficients[it]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.ifEmpty { listOf(ring.zero) }
|
.ifEmpty { listOf(constantZero) }
|
||||||
)
|
)
|
||||||
public override operator fun Polynomial<C>.times(other: Polynomial<C>): Polynomial<C> {
|
public override operator fun Polynomial<C>.times(other: Polynomial<C>): Polynomial<C> {
|
||||||
val thisDegree = degree
|
val thisDegree = degree
|
||||||
@ -321,7 +321,7 @@ public open class PolynomialSpace<C, A : Ring<C>>(
|
|||||||
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?
|
||||||
|
|
||||||
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(constantZero))
|
||||||
|
|
||||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals")
|
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "CovariantEquals")
|
||||||
public override infix fun Polynomial<C>.equalsTo(other: Polynomial<C>): Boolean =
|
public override infix fun Polynomial<C>.equalsTo(other: Polynomial<C>): Boolean =
|
||||||
@ -337,12 +337,12 @@ public open class PolynomialSpace<C, A : Ring<C>>(
|
|||||||
|
|
||||||
// region Polynomial properties
|
// region Polynomial properties
|
||||||
|
|
||||||
public override val Polynomial<C>.degree: Int get() = coefficients.indexOfLast { it != ring.zero }
|
public override val Polynomial<C>.degree: Int get() = coefficients.indexOfLast { it != constantZero }
|
||||||
|
|
||||||
public override fun Polynomial<C>.asConstantOrNull(): C? =
|
public override fun Polynomial<C>.asConstantOrNull(): C? =
|
||||||
with(coefficients) {
|
with(coefficients) {
|
||||||
when {
|
when {
|
||||||
isEmpty() -> ring.zero
|
isEmpty() -> constantZero
|
||||||
degree > 0 -> null
|
degree > 0 -> null
|
||||||
else -> first()
|
else -> first()
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.functions
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.*
|
||||||
@ -270,19 +275,6 @@ public class RationalFunctionSpace<C, A : Ring<C>> (
|
|||||||
denominator * other.denominator
|
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).
|
* Instance of zero rational function (zero of the rational functions ring).
|
||||||
*/
|
*/
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.functions
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.*
|
||||||
@ -30,7 +35,7 @@ import kotlin.contracts.*
|
|||||||
//fun <C, A: Ring<C>> power(arg: Variable, pow: UInt): LabeledPolynomial<C> =
|
//fun <C, A: Ring<C>> power(arg: Variable, pow: UInt): LabeledPolynomial<C> =
|
||||||
// if (pow == 0U) one
|
// if (pow == 0U) one
|
||||||
// else LabeledPolynomial<C>(mapOf(
|
// else LabeledPolynomial<C>(mapOf(
|
||||||
// mapOf(arg to pow) to ring.one
|
// mapOf(arg to pow) to constantOne
|
||||||
// ))
|
// ))
|
||||||
//
|
//
|
||||||
//// endregion
|
//// endregion
|
||||||
|
@ -0,0 +1,130 @@
|
|||||||
|
package math.polynomials
|
||||||
|
|
||||||
|
import math.ringsAndFields.*
|
||||||
|
import space.kscience.kmath.functions.LabeledRationalFunction
|
||||||
|
|
||||||
|
|
||||||
|
fun <T: Ring<T>> T.toLabeledRationalFunction() = LabeledRationalFunction(this.toLabeledPolynomial())
|
||||||
|
|
||||||
|
// region Operator extensions
|
||||||
|
|
||||||
|
// region Field case
|
||||||
|
|
||||||
|
fun <T: Field<T>> LabeledRationalFunction<T>.reduced(): LabeledRationalFunction<T> {
|
||||||
|
val greatestCommonDivider = polynomialGCD(numerator, denominator)
|
||||||
|
return LabeledRationalFunction(
|
||||||
|
numerator / greatestCommonDivider,
|
||||||
|
denominator / greatestCommonDivider
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Constants
|
||||||
|
|
||||||
|
operator fun <T: Ring<T>> T.plus(other: LabeledRationalFunction<T>) = other + this
|
||||||
|
operator fun <T: Ring<T>> Integer.plus(other: LabeledRationalFunction<T>) = other + this
|
||||||
|
operator fun <T: Ring<T>> Int.plus(other: LabeledRationalFunction<T>) = other + this
|
||||||
|
operator fun <T: Ring<T>> Long.plus(other: LabeledRationalFunction<T>) = other + this
|
||||||
|
|
||||||
|
operator fun <T: Ring<T>> T.minus(other: LabeledRationalFunction<T>) = -other + this
|
||||||
|
operator fun <T: Ring<T>> Integer.minus(other: LabeledRationalFunction<T>) = -other + this
|
||||||
|
operator fun <T: Ring<T>> Int.minus(other: LabeledRationalFunction<T>) = -other + this
|
||||||
|
operator fun <T: Ring<T>> Long.minus(other: LabeledRationalFunction<T>) = -other + this
|
||||||
|
|
||||||
|
operator fun <T: Ring<T>> T.times(other: LabeledRationalFunction<T>) = other * this
|
||||||
|
operator fun <T: Ring<T>> Integer.times(other: LabeledRationalFunction<T>) = other * this
|
||||||
|
operator fun <T: Ring<T>> Int.times(other: LabeledRationalFunction<T>) = other * this
|
||||||
|
operator fun <T: Ring<T>> Long.times(other: LabeledRationalFunction<T>) = other * this
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Polynomials
|
||||||
|
|
||||||
|
operator fun <T: Ring<T>> LabeledRationalFunction<T>.plus(other: UnivariatePolynomial<T>) =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator + denominator * other.toLabeledPolynomial(),
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
operator fun <T: Ring<T>> LabeledRationalFunction<T>.plus(other: UnivariateRationalFunction<T>) =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator * other.denominator.toLabeledPolynomial() + denominator * other.numerator.toLabeledPolynomial(),
|
||||||
|
denominator * other.denominator.toLabeledPolynomial()
|
||||||
|
)
|
||||||
|
operator fun <T: Ring<T>> LabeledRationalFunction<T>.plus(other: Polynomial<T>) =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator + denominator * other.toLabeledPolynomial(),
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
operator fun <T: Ring<T>> LabeledRationalFunction<T>.plus(other: NumberedRationalFunction<T>) =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator * other.denominator.toLabeledPolynomial() + denominator * other.numerator.toLabeledPolynomial(),
|
||||||
|
denominator * other.denominator.toLabeledPolynomial()
|
||||||
|
)
|
||||||
|
|
||||||
|
operator fun <T: Ring<T>> LabeledRationalFunction<T>.minus(other: UnivariatePolynomial<T>) =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator - denominator * other.toLabeledPolynomial(),
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
operator fun <T: Ring<T>> LabeledRationalFunction<T>.minus(other: UnivariateRationalFunction<T>) =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator * other.denominator.toLabeledPolynomial() - denominator * other.numerator.toLabeledPolynomial(),
|
||||||
|
denominator * other.denominator.toLabeledPolynomial()
|
||||||
|
)
|
||||||
|
operator fun <T: Ring<T>> LabeledRationalFunction<T>.minus(other: Polynomial<T>) =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator - denominator * other.toLabeledPolynomial(),
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
operator fun <T: Ring<T>> LabeledRationalFunction<T>.minus(other: NumberedRationalFunction<T>) =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator * other.denominator.toLabeledPolynomial() - denominator * other.numerator.toLabeledPolynomial(),
|
||||||
|
denominator * other.denominator.toLabeledPolynomial()
|
||||||
|
)
|
||||||
|
|
||||||
|
operator fun <T: Ring<T>> LabeledRationalFunction<T>.times(other: UnivariatePolynomial<T>) =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator * other.toLabeledPolynomial(),
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
operator fun <T: Ring<T>> LabeledRationalFunction<T>.times(other: UnivariateRationalFunction<T>) =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator * other.numerator.toLabeledPolynomial(),
|
||||||
|
denominator * other.denominator.toLabeledPolynomial()
|
||||||
|
)
|
||||||
|
operator fun <T: Ring<T>> LabeledRationalFunction<T>.times(other: Polynomial<T>) =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator * other.toLabeledPolynomial(),
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
operator fun <T: Ring<T>> LabeledRationalFunction<T>.times(other: NumberedRationalFunction<T>) =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator * other.numerator.toLabeledPolynomial(),
|
||||||
|
denominator * other.denominator.toLabeledPolynomial()
|
||||||
|
)
|
||||||
|
|
||||||
|
operator fun <T: Ring<T>> LabeledRationalFunction<T>.div(other: UnivariatePolynomial<T>) =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator,
|
||||||
|
denominator * other.toLabeledPolynomial()
|
||||||
|
)
|
||||||
|
operator fun <T: Ring<T>> LabeledRationalFunction<T>.div(other: UnivariateRationalFunction<T>) =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator * other.denominator.toLabeledPolynomial(),
|
||||||
|
denominator * other.numerator.toLabeledPolynomial()
|
||||||
|
)
|
||||||
|
operator fun <T: Ring<T>> LabeledRationalFunction<T>.div(other: Polynomial<T>) =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator,
|
||||||
|
denominator * other.toLabeledPolynomial()
|
||||||
|
)
|
||||||
|
operator fun <T: Ring<T>> LabeledRationalFunction<T>.div(other: NumberedRationalFunction<T>) =
|
||||||
|
LabeledRationalFunction(
|
||||||
|
numerator * other.denominator.toLabeledPolynomial(),
|
||||||
|
denominator * other.numerator.toLabeledPolynomial()
|
||||||
|
)
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// endregion
|
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
|
|
||||||
|
//// region Operator extensions
|
||||||
|
//
|
||||||
|
//// region Field case
|
||||||
|
//
|
||||||
|
//fun <T: Field<T>> NumberedRationalFunction<T>.reduced(): NumberedRationalFunction<T> {
|
||||||
|
// val greatestCommonDivider = polynomialGCD(numerator, denominator)
|
||||||
|
// return NumberedRationalFunction(
|
||||||
|
// numerator / greatestCommonDivider,
|
||||||
|
// denominator / greatestCommonDivider
|
||||||
|
// )
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//// endregion
|
||||||
|
//
|
||||||
|
//// endregion
|
@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.functions
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user