Feature: Polynomials and rational functions #469

Merged
lounres merged 132 commits from feature/polynomials into dev 2022-07-28 18:04:06 +03:00
6 changed files with 17 additions and 20 deletions
Showing only changes of commit 2082175af5 - Show all commits

View File

@ -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 }

View File

@ -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)

View File

@ -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 (

View File

@ -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 {

View File

@ -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

View File

@ -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) }