Feature: Polynomials and rational functions #469
@ -49,7 +49,7 @@ internal constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the same degrees description of the monomial, but without zero degrees.
|
* Returns the same degrees' description of the monomial, but without zero degrees.
|
||||||
*/
|
*/
|
||||||
internal fun Map<Symbol, UInt>.cleanUp() = filterValues { it > 0U }
|
internal fun Map<Symbol, UInt>.cleanUp() = filterValues { it > 0U }
|
||||||
|
|
||||||
|
@ -425,7 +425,7 @@ public open class PolynomialSpace<C, A : Ring<C>>(
|
|||||||
public inline fun Polynomial<C>.asFunctionOnPolynomials(): (Polynomial<C>) -> Polynomial<C> = { this.substitute(ring, it) }
|
public inline fun Polynomial<C>.asFunctionOnPolynomials(): (Polynomial<C>) -> Polynomial<C> = { this.substitute(ring, it) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluates the polynomial for the given value [arg].
|
* Evaluates the polynomial for the given value [argument].
|
||||||
*/
|
*/
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
public inline operator fun Polynomial<C>.invoke(argument: C): C = this.substitute(ring, argument)
|
public inline operator fun Polynomial<C>.invoke(argument: C): C = this.substitute(ring, argument)
|
||||||
|
@ -5,10 +5,7 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.functions
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.Ring
|
||||||
import kotlin.jvm.JvmName
|
|
||||||
import kotlin.math.max
|
|
||||||
import kotlin.math.min
|
|
||||||
|
|
||||||
|
|
||||||
public data class RationalFunction<C> internal constructor (
|
public data class RationalFunction<C> internal constructor (
|
||||||
|
@ -65,13 +65,13 @@ import kotlin.contracts.contract
|
|||||||
//
|
//
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crates a [LabeledPolynomialSpace] over received ring.
|
* Creates a [LabeledPolynomialSpace] over a received ring.
|
||||||
*/
|
*/
|
||||||
public fun <C, A : Ring<C>> A.labeledPolynomial(): LabeledPolynomialSpace<C, A> =
|
public fun <C, A : Ring<C>> A.labeledPolynomial(): LabeledPolynomialSpace<C, A> =
|
||||||
LabeledPolynomialSpace(this)
|
LabeledPolynomialSpace(this)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crates a [LabeledPolynomialSpace]'s scope over received ring.
|
* Creates a [LabeledPolynomialSpace]'s scope over a received ring.
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalContracts::class)
|
@OptIn(ExperimentalContracts::class)
|
||||||
public inline fun <C, A : Ring<C>, R> A.labeledPolynomial(block: LabeledPolynomialSpace<C, A>.() -> R): R {
|
public inline fun <C, A : Ring<C>, R> A.labeledPolynomial(block: LabeledPolynomialSpace<C, A>.() -> R): R {
|
||||||
|
@ -42,13 +42,13 @@ import kotlin.math.max
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crates a [NumberedPolynomialSpace] over received ring.
|
* Creates a [NumberedPolynomialSpace] over a received ring.
|
||||||
*/
|
*/
|
||||||
public fun <C, A : Ring<C>> A.numberedPolynomial(): NumberedPolynomialSpace<C, A> =
|
public fun <C, A : Ring<C>> A.numberedPolynomial(): NumberedPolynomialSpace<C, A> =
|
||||||
NumberedPolynomialSpace(this)
|
NumberedPolynomialSpace(this)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crates a [NumberedPolynomialSpace]'s scope over received ring.
|
* Creates a [NumberedPolynomialSpace]'s scope over a received ring.
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalContracts::class)
|
@OptIn(ExperimentalContracts::class)
|
||||||
public inline fun <C, A : Ring<C>, R> A.numberedPolynomial(block: NumberedPolynomialSpace<C, A>.() -> R): R {
|
public inline fun <C, A : Ring<C>, R> A.numberedPolynomial(block: NumberedPolynomialSpace<C, A>.() -> R): R {
|
||||||
@ -279,9 +279,9 @@ public fun NumberedPolynomial<Double>.substitute(args: Map<Int, Double>): Number
|
|||||||
val acc = LinkedHashMap<List<UInt>, Double>(coefficients.size)
|
val acc = LinkedHashMap<List<UInt>, Double>(coefficients.size)
|
||||||
for ((degs, c) in coefficients) {
|
for ((degs, c) in coefficients) {
|
||||||
val newDegs = degs.mapIndexed { index, deg -> if (index !in args) deg else 0u }.cleanUp()
|
val newDegs = degs.mapIndexed { index, deg -> if (index !in args) deg else 0u }.cleanUp()
|
||||||
val newC = args.entries.fold(c) { product, (variable, substitutor) ->
|
val newC = args.entries.fold(c) { product, (variable, substitution) ->
|
||||||
val deg = degs.getOrElse(variable) { 0u }
|
val deg = degs.getOrElse(variable) { 0u }
|
||||||
if (deg == 0u) product else product * substitutor.pow(deg.toInt())
|
if (deg == 0u) product else product * substitution.pow(deg.toInt())
|
||||||
}
|
}
|
||||||
if (newDegs !in acc) acc[newDegs] = newC
|
if (newDegs !in acc) acc[newDegs] = newC
|
||||||
else acc[newDegs] = acc[newDegs]!! + newC
|
else acc[newDegs] = acc[newDegs]!! + newC
|
||||||
@ -298,9 +298,9 @@ public fun <C> NumberedPolynomial<C>.substitute(ring: Ring<C>, args: Map<Int, C>
|
|||||||
val acc = LinkedHashMap<List<UInt>, C>(coefficients.size)
|
val acc = LinkedHashMap<List<UInt>, C>(coefficients.size)
|
||||||
for ((degs, c) in coefficients) {
|
for ((degs, c) in coefficients) {
|
||||||
val newDegs = degs.mapIndexed { index, deg -> if (index !in args) deg else 0u }.cleanUp()
|
val newDegs = degs.mapIndexed { index, deg -> if (index !in args) deg else 0u }.cleanUp()
|
||||||
val newC = args.entries.fold(c) { product, (variable, substitutor) ->
|
val newC = args.entries.fold(c) { product, (variable, substitution) ->
|
||||||
val deg = degs.getOrElse(variable) { 0u }
|
val deg = degs.getOrElse(variable) { 0u }
|
||||||
if (deg == 0u) product else product * power(substitutor, deg)
|
if (deg == 0u) product else product * power(substitution, deg)
|
||||||
}
|
}
|
||||||
if (newDegs !in acc) acc[newDegs] = newC
|
if (newDegs !in acc) acc[newDegs] = newC
|
||||||
else acc[newDegs] = acc[newDegs]!! + newC
|
else acc[newDegs] = acc[newDegs]!! + newC
|
||||||
@ -315,9 +315,9 @@ public fun <C> NumberedPolynomial<C>.substitute(ring: Ring<C>, args: Map<Int, Nu
|
|||||||
val acc = LinkedHashMap<List<UInt>, NumberedPolynomial<C>>(coefficients.size)
|
val acc = LinkedHashMap<List<UInt>, NumberedPolynomial<C>>(coefficients.size)
|
||||||
for ((degs, c) in coefficients) {
|
for ((degs, c) in coefficients) {
|
||||||
val newDegs = degs.mapIndexed { index, deg -> if (index !in args) deg else 0u }.cleanUp()
|
val newDegs = degs.mapIndexed { index, deg -> if (index !in args) deg else 0u }.cleanUp()
|
||||||
val newC = args.entries.fold(c.asNumberedPolynomial()) { product, (variable, substitutor) ->
|
val newC = args.entries.fold(c.asNumberedPolynomial()) { product, (variable, substitution) ->
|
||||||
val deg = degs.getOrElse(variable) { 0u }
|
val deg = degs.getOrElse(variable) { 0u }
|
||||||
if (deg == 0u) product else product * power(substitutor, deg)
|
if (deg == 0u) product else product * power(substitution, deg)
|
||||||
}
|
}
|
||||||
if (newDegs !in acc) acc[newDegs] = c.asNumberedPolynomial()
|
if (newDegs !in acc) acc[newDegs] = c.asNumberedPolynomial()
|
||||||
else acc[newDegs] = acc[newDegs]!! + c
|
else acc[newDegs] = acc[newDegs]!! + c
|
||||||
|
@ -22,13 +22,13 @@ import kotlin.math.pow
|
|||||||
// if (degree > -1) Polynomial(coefficients.subList(0, degree + 1)) else zero
|
// if (degree > -1) Polynomial(coefficients.subList(0, degree + 1)) else zero
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crates a [PolynomialSpace] over received ring.
|
* Creates a [PolynomialSpace] over a received ring.
|
||||||
*/
|
*/
|
||||||
public fun <C, A : Ring<C>> A.polynomial(): PolynomialSpace<C, A> =
|
public fun <C, A : Ring<C>> A.polynomial(): PolynomialSpace<C, A> =
|
||||||
PolynomialSpace(this)
|
PolynomialSpace(this)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crates a [PolynomialSpace]'s scope over received ring.
|
* Creates a [PolynomialSpace]'s scope over a received ring.
|
||||||
*/
|
*/
|
||||||
public inline fun <C, A : Ring<C>, R> A.polynomial(block: PolynomialSpace<C, A>.() -> R): R {
|
public inline fun <C, A : Ring<C>, R> A.polynomial(block: PolynomialSpace<C, A>.() -> R): R {
|
||||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||||
@ -36,13 +36,13 @@ public inline fun <C, A : Ring<C>, R> A.polynomial(block: PolynomialSpace<C, A>.
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crates a [ScalablePolynomialSpace] over received scalable ring.
|
* Creates a [ScalablePolynomialSpace] over a received scalable ring.
|
||||||
*/
|
*/
|
||||||
public fun <C, A> A.scalablePolynomial(): ScalablePolynomialSpace<C, A> where A : Ring<C>, A : ScaleOperations<C> =
|
public fun <C, A> A.scalablePolynomial(): ScalablePolynomialSpace<C, A> where A : Ring<C>, A : ScaleOperations<C> =
|
||||||
ScalablePolynomialSpace(this)
|
ScalablePolynomialSpace(this)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crates a [ScalablePolynomialSpace]'s scope over received scalable ring.
|
* Creates a [ScalablePolynomialSpace]'s scope over a received scalable ring.
|
||||||
*/
|
*/
|
||||||
public inline fun <C, A, R> A.scalablePolynomial(block: ScalablePolynomialSpace<C, A>.() -> R): R where A : Ring<C>, A : ScaleOperations<C> {
|
public inline fun <C, A, R> A.scalablePolynomial(block: ScalablePolynomialSpace<C, A>.() -> R): R where A : Ring<C>, A : ScaleOperations<C> {
|
||||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||||
|
Loading…
Reference in New Issue
Block a user