forked from kscience/kmath
Minimise appearance of new feature, leave only upgrades.
This commit is contained in:
parent
51dd72e48f
commit
f726e6d0f1
@ -1,387 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
@file:Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress")
|
|
||||||
|
|
||||||
package space.kscience.kmath.functions
|
|
||||||
|
|
||||||
import space.kscience.kmath.operations.Ring
|
|
||||||
import space.kscience.kmath.operations.ScaleOperations
|
|
||||||
import space.kscience.kmath.operations.invoke
|
|
||||||
import kotlin.math.max
|
|
||||||
import kotlin.math.min
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents univariate polynomial that stores its coefficients in a [List].
|
|
||||||
*
|
|
||||||
* @param C the type of constants.
|
|
||||||
*/
|
|
||||||
public data class ListPolynomial<C>(
|
|
||||||
/**
|
|
||||||
* List that contains coefficients of the polynomial. Every monomial `a x^d` is stored as a coefficient `a` placed
|
|
||||||
* into the list at index `d`. For example, coefficients of a polynomial `5 x^2 - 6` can be represented as
|
|
||||||
* ```
|
|
||||||
* listOf(
|
|
||||||
* -6, // -6 +
|
|
||||||
* 0, // 0 x +
|
|
||||||
* 5, // 5 x^2
|
|
||||||
* )
|
|
||||||
* ```
|
|
||||||
* and also as
|
|
||||||
* ```
|
|
||||||
* listOf(
|
|
||||||
* -6, // -6 +
|
|
||||||
* 0, // 0 x +
|
|
||||||
* 5, // 5 x^2
|
|
||||||
* 0, // 0 x^3
|
|
||||||
* 0, // 0 x^4
|
|
||||||
* )
|
|
||||||
* ```
|
|
||||||
* It is not prohibited to put extra zeros at end of the list (as for `0x^3` and `0x^4` in the example). But the
|
|
||||||
* longer the coefficients list the worse performance of arithmetical operations performed on it. Thus, it is
|
|
||||||
* recommended not to put (or even to remove) extra (or useless) coefficients at the end of the coefficients list.
|
|
||||||
*/
|
|
||||||
public val coefficients: List<C>
|
|
||||||
) : Polynomial<C> {
|
|
||||||
override fun toString(): String = "ListPolynomial$coefficients"
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Arithmetic context for univariate polynomials with coefficients stored as a [List] constructed with the provided
|
|
||||||
* [ring] of constants.
|
|
||||||
*
|
|
||||||
* @param C the type of constants. Polynomials have them a coefficients in their terms.
|
|
||||||
* @param A type of provided underlying ring of constants. It's [Ring] of [C].
|
|
||||||
* @param ring underlying ring of constants of type [A].
|
|
||||||
*/
|
|
||||||
public open class ListPolynomialSpace<C, A : Ring<C>>(
|
|
||||||
public override val ring: A,
|
|
||||||
) : PolynomialSpaceOverRing<C, ListPolynomial<C>, A> {
|
|
||||||
/**
|
|
||||||
* Returns sum of the polynomial and the integer represented as a polynomial.
|
|
||||||
*
|
|
||||||
* The operation is equivalent to adding [other] copies of unit polynomial to [this].
|
|
||||||
*/
|
|
||||||
public override operator fun ListPolynomial<C>.plus(other: Int): ListPolynomial<C> =
|
|
||||||
if (other == 0) this
|
|
||||||
else
|
|
||||||
ListPolynomial(
|
|
||||||
coefficients
|
|
||||||
.toMutableList()
|
|
||||||
.apply {
|
|
||||||
val result = getOrElse(0) { constantZero } + other
|
|
||||||
|
|
||||||
if(size == 0) add(result)
|
|
||||||
else this[0] = result
|
|
||||||
}
|
|
||||||
)
|
|
||||||
/**
|
|
||||||
* Returns difference between the polynomial and the integer represented as a polynomial.
|
|
||||||
*
|
|
||||||
* The operation is equivalent to subtraction [other] copies of unit polynomial from [this].
|
|
||||||
*/
|
|
||||||
public override operator fun ListPolynomial<C>.minus(other: Int): ListPolynomial<C> =
|
|
||||||
if (other == 0) this
|
|
||||||
else
|
|
||||||
ListPolynomial(
|
|
||||||
coefficients
|
|
||||||
.toMutableList()
|
|
||||||
.apply {
|
|
||||||
val result = getOrElse(0) { constantZero } - other
|
|
||||||
|
|
||||||
if(size == 0) add(result)
|
|
||||||
else this[0] = result
|
|
||||||
}
|
|
||||||
)
|
|
||||||
/**
|
|
||||||
* Returns product of the polynomial and the integer represented as a polynomial.
|
|
||||||
*
|
|
||||||
* The operation is equivalent to sum of [other] copies of [this].
|
|
||||||
*/
|
|
||||||
public override operator fun ListPolynomial<C>.times(other: Int): ListPolynomial<C> =
|
|
||||||
when (other) {
|
|
||||||
0 -> zero
|
|
||||||
1 -> this
|
|
||||||
else -> ListPolynomial(
|
|
||||||
coefficients
|
|
||||||
.toMutableList()
|
|
||||||
.apply {
|
|
||||||
for (deg in indices) this[deg] = this[deg] * other
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns sum of the integer represented as a polynomial and the polynomial.
|
|
||||||
*
|
|
||||||
* The operation is equivalent to adding [this] copies of unit polynomial to [other].
|
|
||||||
*/
|
|
||||||
public override operator fun Int.plus(other: ListPolynomial<C>): ListPolynomial<C> =
|
|
||||||
if (this == 0) other
|
|
||||||
else
|
|
||||||
ListPolynomial(
|
|
||||||
other.coefficients
|
|
||||||
.toMutableList()
|
|
||||||
.apply {
|
|
||||||
val result = this@plus + getOrElse(0) { constantZero }
|
|
||||||
|
|
||||||
if(size == 0) add(result)
|
|
||||||
else this[0] = result
|
|
||||||
}
|
|
||||||
)
|
|
||||||
/**
|
|
||||||
* Returns difference between the integer represented as a polynomial and the polynomial.
|
|
||||||
*
|
|
||||||
* The operation is equivalent to subtraction [this] copies of unit polynomial from [other].
|
|
||||||
*/
|
|
||||||
public override operator fun Int.minus(other: ListPolynomial<C>): ListPolynomial<C> =
|
|
||||||
ListPolynomial(
|
|
||||||
other.coefficients
|
|
||||||
.toMutableList()
|
|
||||||
.apply {
|
|
||||||
if (this@minus == 0) {
|
|
||||||
indices.forEach { this[it] = -this[it] }
|
|
||||||
} else {
|
|
||||||
(1..lastIndex).forEach { this[it] = -this[it] }
|
|
||||||
|
|
||||||
val result = this@minus - getOrElse(0) { constantZero }
|
|
||||||
|
|
||||||
if (size == 0) add(result)
|
|
||||||
else this[0] = result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
/**
|
|
||||||
* Returns product of the integer represented as a polynomial and the polynomial.
|
|
||||||
*
|
|
||||||
* The operation is equivalent to sum of [this] copies of [other].
|
|
||||||
*/
|
|
||||||
public override operator fun Int.times(other: ListPolynomial<C>): ListPolynomial<C> =
|
|
||||||
when (this) {
|
|
||||||
0 -> zero
|
|
||||||
1 -> other
|
|
||||||
else -> ListPolynomial(
|
|
||||||
other.coefficients
|
|
||||||
.toMutableList()
|
|
||||||
.apply {
|
|
||||||
for (deg in indices) this[deg] = this@times * this[deg]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns sum of the constant represented as a polynomial and the polynomial.
|
|
||||||
*/
|
|
||||||
public override operator fun C.plus(other: ListPolynomial<C>): ListPolynomial<C> =
|
|
||||||
with(other.coefficients) {
|
|
||||||
if (isEmpty()) ListPolynomial(listOf(this@plus))
|
|
||||||
else ListPolynomial(
|
|
||||||
toMutableList()
|
|
||||||
.apply {
|
|
||||||
val result = if (size == 0) this@plus else this@plus + get(0)
|
|
||||||
|
|
||||||
if(size == 0) add(result)
|
|
||||||
else this[0] = result
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Returns difference between the constant represented as a polynomial and the polynomial.
|
|
||||||
*/
|
|
||||||
public override operator fun C.minus(other: ListPolynomial<C>): ListPolynomial<C> =
|
|
||||||
with(other.coefficients) {
|
|
||||||
if (isEmpty()) ListPolynomial(listOf(this@minus))
|
|
||||||
else ListPolynomial(
|
|
||||||
toMutableList()
|
|
||||||
.apply {
|
|
||||||
(1 .. lastIndex).forEach { this[it] = -this[it] }
|
|
||||||
|
|
||||||
val result = if (size == 0) this@minus else this@minus - get(0)
|
|
||||||
|
|
||||||
if(size == 0) add(result)
|
|
||||||
else this[0] = result
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Returns product of the constant represented as a polynomial and the polynomial.
|
|
||||||
*/
|
|
||||||
public override operator fun C.times(other: ListPolynomial<C>): ListPolynomial<C> =
|
|
||||||
ListPolynomial(
|
|
||||||
other.coefficients
|
|
||||||
.toMutableList()
|
|
||||||
.apply {
|
|
||||||
for (deg in indices) this[deg] = this@times * this[deg]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns sum of the constant represented as a polynomial and the polynomial.
|
|
||||||
*/
|
|
||||||
public override operator fun ListPolynomial<C>.plus(other: C): ListPolynomial<C> =
|
|
||||||
with(coefficients) {
|
|
||||||
if (isEmpty()) ListPolynomial(listOf(other))
|
|
||||||
else ListPolynomial(
|
|
||||||
toMutableList()
|
|
||||||
.apply {
|
|
||||||
val result = if (size == 0) other else get(0) + other
|
|
||||||
|
|
||||||
if(size == 0) add(result)
|
|
||||||
else this[0] = result
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Returns difference between the constant represented as a polynomial and the polynomial.
|
|
||||||
*/
|
|
||||||
public override operator fun ListPolynomial<C>.minus(other: C): ListPolynomial<C> =
|
|
||||||
with(coefficients) {
|
|
||||||
if (isEmpty()) ListPolynomial(listOf(-other))
|
|
||||||
else ListPolynomial(
|
|
||||||
toMutableList()
|
|
||||||
.apply {
|
|
||||||
val result = if (size == 0) other else get(0) - other
|
|
||||||
|
|
||||||
if(size == 0) add(result)
|
|
||||||
else this[0] = result
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Returns product of the constant represented as a polynomial and the polynomial.
|
|
||||||
*/
|
|
||||||
public override operator fun ListPolynomial<C>.times(other: C): ListPolynomial<C> =
|
|
||||||
ListPolynomial(
|
|
||||||
coefficients
|
|
||||||
.toMutableList()
|
|
||||||
.apply {
|
|
||||||
for (deg in indices) this[deg] = this[deg] * other
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts the constant [value] to polynomial.
|
|
||||||
*/
|
|
||||||
public override fun number(value: C): ListPolynomial<C> = ListPolynomial(listOf(value))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns negation of the polynomial.
|
|
||||||
*/
|
|
||||||
public override operator fun ListPolynomial<C>.unaryMinus(): ListPolynomial<C> =
|
|
||||||
ListPolynomial(coefficients.map { -it })
|
|
||||||
/**
|
|
||||||
* Returns sum of the polynomials.
|
|
||||||
*/
|
|
||||||
public override operator fun ListPolynomial<C>.plus(other: ListPolynomial<C>): ListPolynomial<C> {
|
|
||||||
val thisDegree = degree
|
|
||||||
val otherDegree = other.degree
|
|
||||||
return ListPolynomial(
|
|
||||||
List(max(thisDegree, otherDegree) + 1) {
|
|
||||||
when {
|
|
||||||
it > thisDegree -> other.coefficients[it]
|
|
||||||
it > otherDegree -> coefficients[it]
|
|
||||||
else -> coefficients[it] + other.coefficients[it]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Returns difference of the polynomials.
|
|
||||||
*/
|
|
||||||
public override operator fun ListPolynomial<C>.minus(other: ListPolynomial<C>): ListPolynomial<C> {
|
|
||||||
val thisDegree = degree
|
|
||||||
val otherDegree = other.degree
|
|
||||||
return ListPolynomial(
|
|
||||||
List(max(thisDegree, otherDegree) + 1) {
|
|
||||||
when {
|
|
||||||
it > thisDegree -> -other.coefficients[it]
|
|
||||||
it > otherDegree -> coefficients[it]
|
|
||||||
else -> coefficients[it] - other.coefficients[it]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Returns product of the polynomials.
|
|
||||||
*/
|
|
||||||
public override operator fun ListPolynomial<C>.times(other: ListPolynomial<C>): ListPolynomial<C> {
|
|
||||||
val thisDegree = degree
|
|
||||||
val otherDegree = other.degree
|
|
||||||
return ListPolynomial(
|
|
||||||
List(thisDegree + otherDegree + 1) { d ->
|
|
||||||
(max(0, d - otherDegree)..min(thisDegree, d))
|
|
||||||
.map { coefficients[it] * other.coefficients[d - it] }
|
|
||||||
.reduce { acc, rational -> acc + rational }
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Raises [arg] to the integer power [exponent].
|
|
||||||
*/ // TODO: To optimize boxing
|
|
||||||
override fun power(arg: ListPolynomial<C>, exponent: UInt): ListPolynomial<C> = super.power(arg, exponent)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instance of zero polynomial (zero of the polynomial ring).
|
|
||||||
*/
|
|
||||||
override val zero: ListPolynomial<C> = ListPolynomial(emptyList())
|
|
||||||
/**
|
|
||||||
* Instance of unit polynomial (unit of the polynomial ring).
|
|
||||||
*/
|
|
||||||
override val one: ListPolynomial<C> by lazy { ListPolynomial(listOf(constantOne)) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is
|
|
||||||
* zero, degree is -1.
|
|
||||||
*/
|
|
||||||
public override val ListPolynomial<C>.degree: Int get() = coefficients.lastIndex
|
|
||||||
|
|
||||||
// TODO: When context receivers will be ready move all of this substitutions and invocations to utilities with
|
|
||||||
// [ListPolynomialSpace] as a context receiver
|
|
||||||
/**
|
|
||||||
* Evaluates value of [this] polynomial on provided [argument].
|
|
||||||
*/
|
|
||||||
public inline fun ListPolynomial<C>.substitute(argument: C): C = substitute(ring, argument)
|
|
||||||
/**
|
|
||||||
* Substitutes provided polynomial [argument] into [this] polynomial.
|
|
||||||
*/
|
|
||||||
public inline fun ListPolynomial<C>.substitute(argument: ListPolynomial<C>): ListPolynomial<C> = substitute(ring, argument)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represent [this] polynomial as a regular context-less function.
|
|
||||||
*/
|
|
||||||
public inline fun ListPolynomial<C>.asFunction(): (C) -> C = asFunctionOver(ring)
|
|
||||||
/**
|
|
||||||
* Represent [this] polynomial as a regular context-less function.
|
|
||||||
*/
|
|
||||||
public inline fun ListPolynomial<C>.asFunctionOfConstant(): (C) -> C = asFunctionOfConstantOver(ring)
|
|
||||||
/**
|
|
||||||
* Represent [this] polynomial as a regular context-less function.
|
|
||||||
*/
|
|
||||||
public inline fun ListPolynomial<C>.asFunctionOfPolynomial(): (ListPolynomial<C>) -> ListPolynomial<C> = asFunctionOfPolynomialOver(ring)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Evaluates value of [this] polynomial on provided [argument].
|
|
||||||
*/
|
|
||||||
public inline operator fun ListPolynomial<C>.invoke(argument: C): C = substitute(ring, argument)
|
|
||||||
/**
|
|
||||||
* Evaluates value of [this] polynomial on provided [argument].
|
|
||||||
*/
|
|
||||||
public inline operator fun ListPolynomial<C>.invoke(argument: ListPolynomial<C>): ListPolynomial<C> = substitute(ring, argument)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Space of polynomials constructed over ring.
|
|
||||||
*
|
|
||||||
* @param C the type of constants. Polynomials have them as a coefficients in their terms.
|
|
||||||
* @param A type of underlying ring of constants. It's [Ring] of [C].
|
|
||||||
* @param ring underlying ring of constants of type [A].
|
|
||||||
*/
|
|
||||||
public class ScalableListPolynomialSpace<C, A>(
|
|
||||||
ring: A,
|
|
||||||
) : ListPolynomialSpace<C, A>(ring), ScaleOperations<ListPolynomial<C>> where A : Ring<C>, A : ScaleOperations<C> {
|
|
||||||
override fun scale(a: ListPolynomial<C>, value: Double): ListPolynomial<C> =
|
|
||||||
ring { ListPolynomial(a.coefficients.map { scale(it, value) }) }
|
|
||||||
}
|
|
@ -27,10 +27,10 @@ public fun interface Piecewise<in T, out R> {
|
|||||||
* @property pieces An ordered list of range-polynomial pairs. The list does not in general guarantee that there are no
|
* @property pieces An ordered list of range-polynomial pairs. The list does not in general guarantee that there are no
|
||||||
* "holes" in it.
|
* "holes" in it.
|
||||||
*/
|
*/
|
||||||
public interface PiecewisePolynomial<T : Comparable<T>> : Piecewise<T, ListPolynomial<T>> {
|
public interface PiecewisePolynomial<T : Comparable<T>> : Piecewise<T, Polynomial<T>> {
|
||||||
public val pieces: Collection<Pair<ClosedRange<T>, ListPolynomial<T>>>
|
public val pieces: Collection<Pair<ClosedRange<T>, Polynomial<T>>>
|
||||||
|
|
||||||
override fun findPiece(arg: T): ListPolynomial<T>?
|
override fun findPiece(arg: T): Polynomial<T>?
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,11 +38,11 @@ public interface PiecewisePolynomial<T : Comparable<T>> : Piecewise<T, ListPolyn
|
|||||||
*/
|
*/
|
||||||
@PerformancePitfall("findPiece method of resulting piecewise is slow")
|
@PerformancePitfall("findPiece method of resulting piecewise is slow")
|
||||||
public fun <T : Comparable<T>> PiecewisePolynomial(
|
public fun <T : Comparable<T>> PiecewisePolynomial(
|
||||||
pieces: Collection<Pair<ClosedRange<T>, ListPolynomial<T>>>,
|
pieces: Collection<Pair<ClosedRange<T>, Polynomial<T>>>,
|
||||||
): PiecewisePolynomial<T> = object : PiecewisePolynomial<T> {
|
): PiecewisePolynomial<T> = object : PiecewisePolynomial<T> {
|
||||||
override val pieces: Collection<Pair<ClosedRange<T>, ListPolynomial<T>>> = pieces
|
override val pieces: Collection<Pair<ClosedRange<T>, Polynomial<T>>> = pieces
|
||||||
|
|
||||||
override fun findPiece(arg: T): ListPolynomial<T>? = pieces.firstOrNull { arg in it.first }?.second
|
override fun findPiece(arg: T): Polynomial<T>? = pieces.firstOrNull { arg in it.first }?.second
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,10 +50,10 @@ public fun <T : Comparable<T>> PiecewisePolynomial(
|
|||||||
* The pieces search is logarithmic.
|
* The pieces search is logarithmic.
|
||||||
*/
|
*/
|
||||||
private class OrderedPiecewisePolynomial<T : Comparable<T>>(
|
private class OrderedPiecewisePolynomial<T : Comparable<T>>(
|
||||||
override val pieces: List<Pair<ClosedRange<T>, ListPolynomial<T>>>,
|
override val pieces: List<Pair<ClosedRange<T>, Polynomial<T>>>,
|
||||||
) : PiecewisePolynomial<T> {
|
) : PiecewisePolynomial<T> {
|
||||||
|
|
||||||
override fun findPiece(arg: T): ListPolynomial<T>? {
|
override fun findPiece(arg: T): Polynomial<T>? {
|
||||||
val index = pieces.binarySearch { (range, _) ->
|
val index = pieces.binarySearch { (range, _) ->
|
||||||
when {
|
when {
|
||||||
arg >= range.endInclusive -> -1
|
arg >= range.endInclusive -> -1
|
||||||
@ -74,7 +74,7 @@ private class OrderedPiecewisePolynomial<T : Comparable<T>>(
|
|||||||
*/
|
*/
|
||||||
public class PiecewiseBuilder<T : Comparable<T>>(delimiter: T) {
|
public class PiecewiseBuilder<T : Comparable<T>>(delimiter: T) {
|
||||||
private val delimiters: MutableList<T> = arrayListOf(delimiter)
|
private val delimiters: MutableList<T> = arrayListOf(delimiter)
|
||||||
private val pieces: MutableList<ListPolynomial<T>> = arrayListOf()
|
private val pieces: MutableList<Polynomial<T>> = arrayListOf()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dynamically adds a piece to the right side (beyond maximum argument value of previous piece)
|
* Dynamically adds a piece to the right side (beyond maximum argument value of previous piece)
|
||||||
@ -82,7 +82,7 @@ public class PiecewiseBuilder<T : Comparable<T>>(delimiter: T) {
|
|||||||
* @param right new rightmost position. If is less than current rightmost position, an error is thrown.
|
* @param right new rightmost position. If is less than current rightmost position, an error is thrown.
|
||||||
* @param piece the sub-function.
|
* @param piece the sub-function.
|
||||||
*/
|
*/
|
||||||
public fun putRight(right: T, piece: ListPolynomial<T>) {
|
public fun putRight(right: T, piece: Polynomial<T>) {
|
||||||
require(right > delimiters.last()) { "New delimiter should be to the right of old one" }
|
require(right > delimiters.last()) { "New delimiter should be to the right of old one" }
|
||||||
delimiters += right
|
delimiters += right
|
||||||
pieces += piece
|
pieces += piece
|
||||||
@ -94,7 +94,7 @@ public class PiecewiseBuilder<T : Comparable<T>>(delimiter: T) {
|
|||||||
* @param left the new leftmost position. If is less than current rightmost position, an error is thrown.
|
* @param left the new leftmost position. If is less than current rightmost position, an error is thrown.
|
||||||
* @param piece the sub-function.
|
* @param piece the sub-function.
|
||||||
*/
|
*/
|
||||||
public fun putLeft(left: T, piece: ListPolynomial<T>) {
|
public fun putLeft(left: T, piece: Polynomial<T>) {
|
||||||
require(left < delimiters.first()) { "New delimiter should be to the left of old one" }
|
require(left < delimiters.first()) { "New delimiter should be to the left of old one" }
|
||||||
delimiters.add(0, left)
|
delimiters.add(0, left)
|
||||||
pieces.add(0, piece)
|
pieces.add(0, piece)
|
||||||
|
@ -3,500 +3,299 @@
|
|||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@file:Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress", "PARAMETER_NAME_CHANGED_ON_OVERRIDE")
|
||||||
|
|
||||||
package space.kscience.kmath.functions
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
import space.kscience.kmath.operations.Ring
|
import space.kscience.kmath.operations.Ring
|
||||||
|
import space.kscience.kmath.operations.ScaleOperations
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import kotlin.js.JsName
|
import kotlin.jvm.JvmInline
|
||||||
import kotlin.jvm.JvmName
|
import kotlin.math.max
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstraction of polynomials.
|
* Represents univariate polynomial that stores its coefficients in a [List].
|
||||||
|
*
|
||||||
|
* @param C the type of constants.
|
||||||
*/
|
*/
|
||||||
public interface Polynomial<C>
|
@JvmInline
|
||||||
|
public value class Polynomial<C>(
|
||||||
|
/**
|
||||||
|
* List that contains coefficients of the polynomial. Every monomial `a x^d` is stored as a coefficient `a` placed
|
||||||
|
* into the list at index `d`. For example, coefficients of a polynomial `5 x^2 - 6` can be represented as
|
||||||
|
* ```
|
||||||
|
* listOf(
|
||||||
|
* -6, // -6 +
|
||||||
|
* 0, // 0 x +
|
||||||
|
* 5, // 5 x^2
|
||||||
|
* )
|
||||||
|
* ```
|
||||||
|
* and also as
|
||||||
|
* ```
|
||||||
|
* listOf(
|
||||||
|
* -6, // -6 +
|
||||||
|
* 0, // 0 x +
|
||||||
|
* 5, // 5 x^2
|
||||||
|
* 0, // 0 x^3
|
||||||
|
* 0, // 0 x^4
|
||||||
|
* )
|
||||||
|
* ```
|
||||||
|
* It is not prohibited to put extra zeros at end of the list (as for `0x^3` and `0x^4` in the example). But the
|
||||||
|
* longer the coefficients list the worse performance of arithmetical operations performed on it. Thus, it is
|
||||||
|
* recommended not to put (or even to remove) extra (or useless) coefficients at the end of the coefficients list.
|
||||||
|
*/
|
||||||
|
public val coefficients: List<C>
|
||||||
|
) {
|
||||||
|
override fun toString(): String = "ListPolynomial$coefficients"
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstraction of ring of polynomials of type [P] over ring of constants of type [C].
|
* Arithmetic context for univariate polynomials with coefficients stored as a [List] constructed with the provided
|
||||||
|
* [ring] of constants.
|
||||||
*
|
*
|
||||||
* @param C the type of constants. Polynomials have them as coefficients in their terms.
|
* @param C the type of constants. Polynomials have them a coefficients in their terms.
|
||||||
* @param P the type of polynomials.
|
* @param A type of provided underlying ring of constants. It's [Ring] of [C].
|
||||||
|
* @param ring underlying ring of constants of type [A].
|
||||||
*/
|
*/
|
||||||
@Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") // FIXME: Waiting for KT-31420
|
public open class ListPolynomialSpace<C, A : Ring<C>>(
|
||||||
public interface PolynomialSpace<C, P: Polynomial<C>> : Ring<P> {
|
|
||||||
/**
|
/**
|
||||||
* Returns sum of the constant and the integer represented as a constant (member of underlying ring).
|
* Underlying ring of constants. Its operations on constants are inherited by local operations on constants.
|
||||||
*
|
|
||||||
* The operation is equivalent to adding [other] copies of unit of underlying ring to [this].
|
|
||||||
*/
|
*/
|
||||||
public operator fun C.plus(other: Int): C
|
public val ring: A,
|
||||||
/**
|
) : Ring<Polynomial<C>> {
|
||||||
* Returns difference between the constant and the integer represented as a constant (member of underlying ring).
|
|
||||||
*
|
|
||||||
* The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this].
|
|
||||||
*/
|
|
||||||
public operator fun C.minus(other: Int): C
|
|
||||||
/**
|
|
||||||
* Returns product of the constant and the integer represented as a constant (member of underlying ring).
|
|
||||||
*
|
|
||||||
* The operation is equivalent to sum of [other] copies of [this].
|
|
||||||
*/
|
|
||||||
public operator fun C.times(other: Int): C
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns sum of the integer represented as a constant (member of underlying ring) and the constant.
|
|
||||||
*
|
|
||||||
* The operation is equivalent to adding [this] copies of unit of underlying ring to [other].
|
|
||||||
*/
|
|
||||||
public operator fun Int.plus(other: C): C
|
|
||||||
/**
|
|
||||||
* Returns difference between the integer represented as a constant (member of underlying ring) and the constant.
|
|
||||||
*
|
|
||||||
* The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other].
|
|
||||||
*/
|
|
||||||
public operator fun Int.minus(other: C): C
|
|
||||||
/**
|
|
||||||
* Returns product of the integer represented as a constant (member of underlying ring) and the constant.
|
|
||||||
*
|
|
||||||
* The operation is equivalent to sum of [this] copies of [other].
|
|
||||||
*/
|
|
||||||
public operator fun Int.times(other: C): C
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts the integer [value] to constant.
|
|
||||||
*/
|
|
||||||
public fun constantNumber(value: Int): C = constantOne * value
|
|
||||||
/**
|
|
||||||
* Converts the integer to constant.
|
|
||||||
*/
|
|
||||||
public fun Int.asConstant(): C = constantNumber(this)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns sum of the polynomial and the integer represented as a polynomial.
|
|
||||||
*
|
|
||||||
* The operation is equivalent to adding [other] copies of unit polynomial to [this].
|
|
||||||
*/
|
|
||||||
public operator fun P.plus(other: Int): P = addMultipliedByDoubling(this, one, other)
|
|
||||||
/**
|
|
||||||
* Returns difference between the polynomial and the integer represented as a polynomial.
|
|
||||||
*
|
|
||||||
* The operation is equivalent to subtraction [other] copies of unit polynomial from [this].
|
|
||||||
*/
|
|
||||||
public operator fun P.minus(other: Int): P = addMultipliedByDoubling(this, one, -other)
|
|
||||||
/**
|
|
||||||
* Returns product of the polynomial and the integer represented as a polynomial.
|
|
||||||
*
|
|
||||||
* The operation is equivalent to sum of [other] copies of [this].
|
|
||||||
*/
|
|
||||||
public operator fun P.times(other: Int): P = multiplyByDoubling(this, other)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns sum of the integer represented as a polynomial and the polynomial.
|
|
||||||
*
|
|
||||||
* The operation is equivalent to adding [this] copies of unit polynomial to [other].
|
|
||||||
*/
|
|
||||||
public operator fun Int.plus(other: P): P = addMultipliedByDoubling(other, one, this)
|
|
||||||
/**
|
|
||||||
* Returns difference between the integer represented as a polynomial and the polynomial.
|
|
||||||
*
|
|
||||||
* The operation is equivalent to subtraction [this] copies of unit polynomial from [other].
|
|
||||||
*/
|
|
||||||
public operator fun Int.minus(other: P): P = addMultipliedByDoubling(-other, one, this)
|
|
||||||
/**
|
|
||||||
* Returns product of the integer represented as a polynomial and the polynomial.
|
|
||||||
*
|
|
||||||
* The operation is equivalent to sum of [this] copies of [other].
|
|
||||||
*/
|
|
||||||
public operator fun Int.times(other: P): P = multiplyByDoubling(other, this)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts the integer [value] to polynomial.
|
|
||||||
*/
|
|
||||||
public fun number(value: Int): P = number(constantNumber(value))
|
|
||||||
/**
|
|
||||||
* Converts the integer to polynomial.
|
|
||||||
*/
|
|
||||||
public fun Int.asPolynomial(): P = number(this)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the same constant.
|
|
||||||
*/
|
|
||||||
@JvmName("unaryPlusConstant")
|
|
||||||
@JsName("unaryPlusConstant")
|
|
||||||
public operator fun C.unaryPlus(): C = this
|
|
||||||
/**
|
|
||||||
* Returns negation of the constant.
|
|
||||||
*/
|
|
||||||
@JvmName("unaryMinusConstant")
|
|
||||||
@JsName("unaryMinusConstant")
|
|
||||||
public operator fun C.unaryMinus(): C
|
|
||||||
/**
|
|
||||||
* Returns sum of the constants.
|
|
||||||
*/
|
|
||||||
@JvmName("plusConstantConstant")
|
|
||||||
@JsName("plusConstantConstant")
|
|
||||||
public operator fun C.plus(other: C): C
|
|
||||||
/**
|
|
||||||
* Returns difference of the constants.
|
|
||||||
*/
|
|
||||||
@JvmName("minusConstantConstant")
|
|
||||||
@JsName("minusConstantConstant")
|
|
||||||
public operator fun C.minus(other: C): C
|
|
||||||
/**
|
|
||||||
* Returns product of the constants.
|
|
||||||
*/
|
|
||||||
@JvmName("timesConstantConstant")
|
|
||||||
@JsName("timesConstantConstant")
|
|
||||||
public operator fun C.times(other: C): C
|
|
||||||
/**
|
|
||||||
* Raises [arg] to the integer power [exponent].
|
|
||||||
*/
|
|
||||||
@JvmName("powerConstant")
|
|
||||||
@JsName("powerConstant")
|
|
||||||
public fun power(arg: C, exponent: UInt) : C
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instance of zero constant (zero of the underlying ring).
|
* Instance of zero constant (zero of the underlying ring).
|
||||||
*/
|
*/
|
||||||
public val constantZero: C
|
public val constantZero: C get() = ring.zero
|
||||||
/**
|
/**
|
||||||
* Instance of unit constant (unit of the underlying ring).
|
* Instance of unit constant (unit of the underlying ring).
|
||||||
*/
|
*/
|
||||||
public val constantOne: C
|
public val constantOne: C get() = ring.one
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns sum of the constant represented as a polynomial and the polynomial.
|
* Returns sum of the constant represented as a polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
public operator fun C.plus(other: P): P
|
public operator fun C.plus(other: Polynomial<C>): Polynomial<C> =
|
||||||
|
with(ring) {
|
||||||
|
with(other.coefficients) {
|
||||||
|
if (isEmpty()) Polynomial(listOf(this@plus))
|
||||||
|
else Polynomial(
|
||||||
|
toMutableList()
|
||||||
|
.apply {
|
||||||
|
val result = if (size == 0) this@plus else this@plus + get(0)
|
||||||
|
|
||||||
|
if (size == 0) add(result)
|
||||||
|
else this[0] = result
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Returns difference between the constant represented as a polynomial and the polynomial.
|
* Returns difference between the constant represented as a polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
public operator fun C.minus(other: P): P
|
public operator fun C.minus(other: Polynomial<C>): Polynomial<C> =
|
||||||
|
with(ring) {
|
||||||
|
with(other.coefficients) {
|
||||||
|
if (isEmpty()) Polynomial(listOf(this@minus))
|
||||||
|
else Polynomial(
|
||||||
|
toMutableList()
|
||||||
|
.apply {
|
||||||
|
(1..lastIndex).forEach { this[it] = -this[it] }
|
||||||
|
|
||||||
|
val result = if (size == 0) this@minus else this@minus - get(0)
|
||||||
|
|
||||||
|
if (size == 0) add(result)
|
||||||
|
else this[0] = result
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Returns product of the constant represented as a polynomial and the polynomial.
|
* Returns product of the constant represented as a polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
public operator fun C.times(other: P): P
|
public operator fun C.times(other: Polynomial<C>): Polynomial<C> =
|
||||||
|
with(ring) {
|
||||||
|
Polynomial(
|
||||||
|
other.coefficients
|
||||||
|
.toMutableList()
|
||||||
|
.apply {
|
||||||
|
for (deg in indices) this[deg] = this@times * this[deg]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns sum of the constant represented as a polynomial and the polynomial.
|
* Returns sum of the constant represented as a polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
public operator fun P.plus(other: C): P
|
public operator fun Polynomial<C>.plus(other: C): Polynomial<C> =
|
||||||
|
with(ring) {
|
||||||
|
with(coefficients) {
|
||||||
|
if (isEmpty()) Polynomial(listOf(other))
|
||||||
|
else Polynomial(
|
||||||
|
toMutableList()
|
||||||
|
.apply {
|
||||||
|
val result = if (size == 0) other else get(0) + other
|
||||||
|
|
||||||
|
if (size == 0) add(result)
|
||||||
|
else this[0] = result
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Returns difference between the constant represented as a polynomial and the polynomial.
|
* Returns difference between the constant represented as a polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
public operator fun P.minus(other: C): P
|
public operator fun Polynomial<C>.minus(other: C): Polynomial<C> =
|
||||||
|
with(ring) {
|
||||||
|
with(coefficients) {
|
||||||
|
if (isEmpty()) Polynomial(listOf(-other))
|
||||||
|
else Polynomial(
|
||||||
|
toMutableList()
|
||||||
|
.apply {
|
||||||
|
val result = if (size == 0) other else get(0) - other
|
||||||
|
|
||||||
|
if (size == 0) add(result)
|
||||||
|
else this[0] = result
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Returns product of the constant represented as a polynomial and the polynomial.
|
* Returns product of the constant represented as a polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
public operator fun P.times(other: C): P
|
public operator fun Polynomial<C>.times(other: C): Polynomial<C> =
|
||||||
|
with(ring) {
|
||||||
|
Polynomial(
|
||||||
|
coefficients
|
||||||
|
.toMutableList()
|
||||||
|
.apply {
|
||||||
|
for (deg in indices) this[deg] = this[deg] * other
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the constant [value] to polynomial.
|
* Converts the constant [value] to polynomial.
|
||||||
*/
|
*/
|
||||||
public fun number(value: C): P = one * value
|
public fun number(value: C): Polynomial<C> = Polynomial(listOf(value))
|
||||||
/**
|
/**
|
||||||
* Converts the constant to polynomial.
|
* Converts the constant to polynomial.
|
||||||
*/
|
*/
|
||||||
public fun C.asPolynomial(): P = number(this)
|
public fun C.asPolynomial(): Polynomial<C> = number(this)
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the same polynomial.
|
|
||||||
*/
|
|
||||||
public override operator fun P.unaryPlus(): P = this
|
|
||||||
/**
|
/**
|
||||||
* Returns negation of the polynomial.
|
* Returns negation of the polynomial.
|
||||||
*/
|
*/
|
||||||
public override operator fun P.unaryMinus(): P
|
public override operator fun Polynomial<C>.unaryMinus(): Polynomial<C> =
|
||||||
|
with(ring) {
|
||||||
|
Polynomial(coefficients.map { -it })
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Returns sum of the polynomials.
|
* Returns sum of the polynomials.
|
||||||
*/
|
*/
|
||||||
public override operator fun P.plus(other: P): P
|
public override operator fun Polynomial<C>.plus(other: Polynomial<C>): Polynomial<C> {
|
||||||
|
with(ring) {
|
||||||
|
val thisDegree = degree
|
||||||
|
val otherDegree = other.degree
|
||||||
|
return Polynomial(
|
||||||
|
List(max(thisDegree, otherDegree) + 1) {
|
||||||
|
when {
|
||||||
|
it > thisDegree -> other.coefficients[it]
|
||||||
|
it > otherDegree -> coefficients[it]
|
||||||
|
else -> coefficients[it] + other.coefficients[it]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Returns difference of the polynomials.
|
* Returns difference of the polynomials.
|
||||||
*/
|
*/
|
||||||
public override operator fun P.minus(other: P): P
|
public override operator fun Polynomial<C>.minus(other: Polynomial<C>): Polynomial<C> {
|
||||||
|
with(ring) {
|
||||||
|
val thisDegree = degree
|
||||||
|
val otherDegree = other.degree
|
||||||
|
return Polynomial(
|
||||||
|
List(max(thisDegree, otherDegree) + 1) {
|
||||||
|
when {
|
||||||
|
it > thisDegree -> -other.coefficients[it]
|
||||||
|
it > otherDegree -> coefficients[it]
|
||||||
|
else -> coefficients[it] - other.coefficients[it]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Returns product of the polynomials.
|
* Returns product of the polynomials.
|
||||||
*/
|
*/
|
||||||
public override operator fun P.times(other: P): P
|
public override operator fun Polynomial<C>.times(other: Polynomial<C>): Polynomial<C> {
|
||||||
|
with(ring) {
|
||||||
|
val thisDegree = degree
|
||||||
|
val otherDegree = other.degree
|
||||||
|
return Polynomial(
|
||||||
|
List(thisDegree + otherDegree + 1) { d ->
|
||||||
|
(max(0, d - otherDegree)..min(thisDegree, d))
|
||||||
|
.map { coefficients[it] * other.coefficients[d - it] }
|
||||||
|
.reduce { acc, rational -> acc + rational }
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Raises [arg] to the integer power [exponent].
|
* Raises [arg] to the integer power [exponent].
|
||||||
*/
|
*/ // TODO: To optimize boxing
|
||||||
public override fun power(arg: P, exponent: UInt) : P = exponentiateBySquaring(arg, exponent)
|
override fun power(arg: Polynomial<C>, exponent: UInt): Polynomial<C> = exponentiateBySquaring(arg, exponent)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instance of zero polynomial (zero of the polynomial ring).
|
* Instance of zero polynomial (zero of the polynomial ring).
|
||||||
*/
|
*/
|
||||||
public override val zero: P
|
override val zero: Polynomial<C> = Polynomial(emptyList())
|
||||||
/**
|
/**
|
||||||
* Instance of unit polynomial (unit of the polynomial ring).
|
* Instance of unit polynomial (unit of the polynomial ring).
|
||||||
*/
|
*/
|
||||||
public override val one: P
|
override val one: Polynomial<C> by lazy { Polynomial(listOf(constantOne)) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is
|
* Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is
|
||||||
* zero, degree is -1.
|
* zero, degree is -1.
|
||||||
*/
|
*/
|
||||||
public val P.degree: Int
|
public val Polynomial<C>.degree: Int get() = coefficients.lastIndex
|
||||||
|
|
||||||
override fun add(left: P, right: P): P = left + right
|
override fun add(left: Polynomial<C>, right: Polynomial<C>): Polynomial<C> = left + right
|
||||||
override fun multiply(left: P, right: P): P = left * right
|
override fun multiply(left: Polynomial<C>, right: Polynomial<C>): Polynomial<C> = left * right
|
||||||
|
|
||||||
|
// TODO: When context receivers will be ready move all of this substitutions and invocations to utilities with
|
||||||
|
// [ListPolynomialSpace] as a context receiver
|
||||||
|
/**
|
||||||
|
* Evaluates value of [this] polynomial on provided [argument].
|
||||||
|
*/
|
||||||
|
public inline fun Polynomial<C>.substitute(argument: C): C = substitute(ring, argument)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represent [this] polynomial as a regular context-less function.
|
||||||
|
*/
|
||||||
|
public inline fun Polynomial<C>.asFunction(): (C) -> C = asFunctionOver(ring)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates value of [this] polynomial on provided [argument].
|
||||||
|
*/
|
||||||
|
public inline operator fun Polynomial<C>.invoke(argument: C): C = substitute(ring, argument)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstraction of ring of polynomials of type [P] over ring of constants of type [C]. It also assumes that there is
|
* Space of polynomials constructed over ring.
|
||||||
* provided [ring] (of type [A]), that provides constant-wise operations.
|
|
||||||
*
|
*
|
||||||
* @param C the type of constants. Polynomials have them as coefficients in their terms.
|
* @param C the type of constants. Polynomials have them as a coefficients in their terms.
|
||||||
* @param P the type of polynomials.
|
* @param A type of underlying ring of constants. It's [Ring] of [C].
|
||||||
* @param A the type of algebraic structure (precisely, of ring) provided for constants.
|
* @param ring underlying ring of constants of type [A].
|
||||||
*/
|
*/
|
||||||
@Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420
|
public class ScalableListPolynomialSpace<C, A>(
|
||||||
public interface PolynomialSpaceOverRing<C, P: Polynomial<C>, A: Ring<C>> : PolynomialSpace<C, P> {
|
ring: A,
|
||||||
|
) : ListPolynomialSpace<C, A>(ring), ScaleOperations<Polynomial<C>> where A : Ring<C>, A : ScaleOperations<C> {
|
||||||
/**
|
override fun scale(a: Polynomial<C>, value: Double): Polynomial<C> =
|
||||||
* Underlying ring of constants. Its operations on constants are inherited by local operations on constants.
|
ring { Polynomial(a.coefficients.map { scale(it, value) }) }
|
||||||
*/
|
|
||||||
public val ring: A
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns sum of the constant and the integer represented as a constant (member of underlying ring).
|
|
||||||
*
|
|
||||||
* The operation is equivalent to adding [other] copies of unit of underlying ring to [this].
|
|
||||||
*/
|
|
||||||
public override operator fun C.plus(other: Int): C = ring { addMultipliedByDoubling(this@plus, one, other) }
|
|
||||||
/**
|
|
||||||
* Returns difference between the constant and the integer represented as a constant (member of underlying ring).
|
|
||||||
*
|
|
||||||
* The operation is equivalent to subtraction [other] copies of unit of underlying ring from [this].
|
|
||||||
*/
|
|
||||||
public override operator fun C.minus(other: Int): C = ring { addMultipliedByDoubling(this@minus, one, -other) }
|
|
||||||
/**
|
|
||||||
* Returns product of the constant and the integer represented as a constant (member of underlying ring).
|
|
||||||
*
|
|
||||||
* The operation is equivalent to sum of [other] copies of [this].
|
|
||||||
*/
|
|
||||||
public override operator fun C.times(other: Int): C = ring { multiplyByDoubling(this@times, other) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns sum of the integer represented as a constant (member of underlying ring) and the constant.
|
|
||||||
*
|
|
||||||
* The operation is equivalent to adding [this] copies of unit of underlying ring to [other].
|
|
||||||
*/
|
|
||||||
public override operator fun Int.plus(other: C): C = ring { addMultipliedByDoubling(other, one, this@plus) }
|
|
||||||
/**
|
|
||||||
* Returns difference between the integer represented as a constant (member of underlying ring) and the constant.
|
|
||||||
*
|
|
||||||
* The operation is equivalent to subtraction [this] copies of unit of underlying ring from [other].
|
|
||||||
*/
|
|
||||||
public override operator fun Int.minus(other: C): C = ring { addMultipliedByDoubling(-other, one, this@minus) }
|
|
||||||
/**
|
|
||||||
* Returns product of the integer represented as a constant (member of underlying ring) and the constant.
|
|
||||||
*
|
|
||||||
* The operation is equivalent to sum of [this] copies of [other].
|
|
||||||
*/
|
|
||||||
public override operator fun Int.times(other: C): C = ring { multiplyByDoubling(other, this@times) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns negation of the constant.
|
|
||||||
*/
|
|
||||||
@JvmName("unaryMinusConstant")
|
|
||||||
public override operator fun C.unaryMinus(): C = ring { -this@unaryMinus }
|
|
||||||
/**
|
|
||||||
* Returns sum of the constants.
|
|
||||||
*/
|
|
||||||
@JvmName("plusConstantConstant")
|
|
||||||
public override operator fun C.plus(other: C): C = ring { this@plus + other }
|
|
||||||
/**
|
|
||||||
* Returns difference of the constants.
|
|
||||||
*/
|
|
||||||
@JvmName("minusConstantConstant")
|
|
||||||
public override operator fun C.minus(other: C): C = ring { this@minus - other }
|
|
||||||
/**
|
|
||||||
* Returns product of the constants.
|
|
||||||
*/
|
|
||||||
@JvmName("timesConstantConstant")
|
|
||||||
public override operator fun C.times(other: C): C = ring { this@times * other }
|
|
||||||
/**
|
|
||||||
* Raises [arg] to the integer power [exponent].
|
|
||||||
*/
|
|
||||||
@JvmName("powerConstant")
|
|
||||||
override fun power(arg: C, exponent: UInt): C = ring { power(arg, exponent) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instance of zero constant (zero of the underlying ring).
|
|
||||||
*/
|
|
||||||
public override val constantZero: C get() = ring.zero
|
|
||||||
/**
|
|
||||||
* Instance of unit constant (unit of the underlying ring).
|
|
||||||
*/
|
|
||||||
public override val constantOne: C get() = ring.one
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstraction of ring of polynomials of type [P] of variables of type [V] and over ring of constants of type [C].
|
|
||||||
*
|
|
||||||
* @param C the type of constants. Polynomials have them as coefficients in their terms.
|
|
||||||
* @param V the type of variables. Polynomials have them in representations of terms.
|
|
||||||
* @param P the type of polynomials.
|
|
||||||
*/
|
|
||||||
@Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420
|
|
||||||
public interface MultivariatePolynomialSpace<C, V, P: Polynomial<C>>: PolynomialSpace<C, P> {
|
|
||||||
/**
|
|
||||||
* Returns sum of the variable represented as a monic monomial and the integer represented as a constant polynomial.
|
|
||||||
*/
|
|
||||||
@JvmName("plusVariableInt")
|
|
||||||
public operator fun V.plus(other: Int): P
|
|
||||||
/**
|
|
||||||
* Returns difference between the variable represented as a monic monomial and the integer represented as a constant polynomial.
|
|
||||||
*/
|
|
||||||
@JvmName("minusVariableInt")
|
|
||||||
public operator fun V.minus(other: Int): P
|
|
||||||
/**
|
|
||||||
* Returns product of the variable represented as a monic monomial and the integer represented as a constant polynomial.
|
|
||||||
*/
|
|
||||||
@JvmName("timesVariableInt")
|
|
||||||
public operator fun V.times(other: Int): P
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns sum of the integer represented as a constant polynomial and the variable represented as a monic monomial.
|
|
||||||
*/
|
|
||||||
@JvmName("plusIntVariable")
|
|
||||||
public operator fun Int.plus(other: V): P
|
|
||||||
/**
|
|
||||||
* Returns difference between the integer represented as a constant polynomial and the variable represented as a monic monomial.
|
|
||||||
*/
|
|
||||||
@JvmName("minusIntVariable")
|
|
||||||
public operator fun Int.minus(other: V): P
|
|
||||||
/**
|
|
||||||
* Returns product of the integer represented as a constant polynomial and the variable represented as a monic monomial.
|
|
||||||
*/
|
|
||||||
@JvmName("timesIntVariable")
|
|
||||||
public operator fun Int.times(other: V): P
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns sum of the variable represented as a monic monomial and the constant represented as a constant polynomial.
|
|
||||||
*/
|
|
||||||
@JvmName("plusVariableConstant")
|
|
||||||
public operator fun V.plus(other: C): P
|
|
||||||
/**
|
|
||||||
* Returns difference between the variable represented as a monic monomial and the constant represented as a constant polynomial.
|
|
||||||
*/
|
|
||||||
@JvmName("minusVariableConstant")
|
|
||||||
public operator fun V.minus(other: C): P
|
|
||||||
/**
|
|
||||||
* Returns product of the variable represented as a monic monomial and the constant represented as a constant polynomial.
|
|
||||||
*/
|
|
||||||
@JvmName("timesVariableConstant")
|
|
||||||
public operator fun V.times(other: C): P
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns sum of the constant represented as a constant polynomial and the variable represented as a monic monomial.
|
|
||||||
*/
|
|
||||||
@JvmName("plusConstantVariable")
|
|
||||||
public operator fun C.plus(other: V): P
|
|
||||||
/**
|
|
||||||
* Returns difference between the constant represented as a constant polynomial and the variable represented as a monic monomial.
|
|
||||||
*/
|
|
||||||
@JvmName("minusConstantVariable")
|
|
||||||
public operator fun C.minus(other: V): P
|
|
||||||
/**
|
|
||||||
* Returns product of the constant represented as a constant polynomial and the variable represented as a monic monomial.
|
|
||||||
*/
|
|
||||||
@JvmName("timesConstantVariable")
|
|
||||||
public operator fun C.times(other: V): P
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the variable as a monic monomial.
|
|
||||||
*/
|
|
||||||
@JvmName("unaryPlusVariable")
|
|
||||||
public operator fun V.unaryPlus(): P
|
|
||||||
/**
|
|
||||||
* Returns negation of representation of the variable as a monic monomial.
|
|
||||||
*/
|
|
||||||
@JvmName("unaryMinusVariable")
|
|
||||||
public operator fun V.unaryMinus(): P
|
|
||||||
/**
|
|
||||||
* Returns sum of the variables represented as monic monomials.
|
|
||||||
*/
|
|
||||||
@JvmName("plusVariableVariable")
|
|
||||||
public operator fun V.plus(other: V): P
|
|
||||||
/**
|
|
||||||
* Returns difference between the variables represented as monic monomials.
|
|
||||||
*/
|
|
||||||
@JvmName("minusVariableVariable")
|
|
||||||
public operator fun V.minus(other: V): P
|
|
||||||
/**
|
|
||||||
* Returns product of the variables represented as monic monomials.
|
|
||||||
*/
|
|
||||||
@JvmName("timesVariableVariable")
|
|
||||||
public operator fun V.times(other: V): P
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the [variable] as a monic monomial.
|
|
||||||
*/
|
|
||||||
@JvmName("numberVariable")
|
|
||||||
public fun number(variable: V): P = +variable
|
|
||||||
/**
|
|
||||||
* Represents the variable as a monic monomial.
|
|
||||||
*/
|
|
||||||
@JvmName("asPolynomialVariable")
|
|
||||||
public fun V.asPolynomial(): P = number(this)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns sum of the variable represented as a monic monomial and the polynomial.
|
|
||||||
*/
|
|
||||||
@JvmName("plusVariablePolynomial")
|
|
||||||
public operator fun V.plus(other: P): P
|
|
||||||
/**
|
|
||||||
* Returns difference between the variable represented as a monic monomial and the polynomial.
|
|
||||||
*/
|
|
||||||
@JvmName("minusVariablePolynomial")
|
|
||||||
public operator fun V.minus(other: P): P
|
|
||||||
/**
|
|
||||||
* Returns product of the variable represented as a monic monomial and the polynomial.
|
|
||||||
*/
|
|
||||||
@JvmName("timesVariablePolynomial")
|
|
||||||
public operator fun V.times(other: P): P
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns sum of the polynomial and the variable represented as a monic monomial.
|
|
||||||
*/
|
|
||||||
@JvmName("plusPolynomialVariable")
|
|
||||||
public operator fun P.plus(other: V): P
|
|
||||||
/**
|
|
||||||
* Returns difference between the polynomial and the variable represented as a monic monomial.
|
|
||||||
*/
|
|
||||||
@JvmName("minusPolynomialVariable")
|
|
||||||
public operator fun P.minus(other: V): P
|
|
||||||
/**
|
|
||||||
* Returns product of the polynomial and the variable represented as a monic monomial.
|
|
||||||
*/
|
|
||||||
@JvmName("timesPolynomialVariable")
|
|
||||||
public operator fun P.times(other: V): P
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 P.degrees: Map<V, UInt>
|
|
||||||
/**
|
|
||||||
* Counts degree of the polynomial by the specified [variable].
|
|
||||||
*/
|
|
||||||
public fun P.degreeBy(variable: V): UInt = degrees.getOrElse(variable) { 0u }
|
|
||||||
/**
|
|
||||||
* Counts degree of the polynomial by the specified [variables].
|
|
||||||
*/
|
|
||||||
public fun P.degreeBy(variables: Collection<V>): UInt
|
|
||||||
/**
|
|
||||||
* Set of all variables that appear in the polynomial in positive exponents.
|
|
||||||
*/
|
|
||||||
public val P.variables: Set<V> get() = degrees.keys
|
|
||||||
/**
|
|
||||||
* Count of all variables that appear in the polynomial in positive exponents.
|
|
||||||
*/
|
|
||||||
public val P.countOfVariables: Int get() = variables.size
|
|
||||||
}
|
}
|
@ -9,101 +9,6 @@ import space.kscience.kmath.operations.*
|
|||||||
|
|
||||||
|
|
||||||
// TODO: All of this should be moved to algebraic structures' place for utilities
|
// TODO: All of this should be moved to algebraic structures' place for utilities
|
||||||
// FIXME: Move receiver to context receiver
|
|
||||||
/**
|
|
||||||
* Returns product of [arg] and integer [multiplier].
|
|
||||||
*
|
|
||||||
* @param arg the multiplicand.
|
|
||||||
* @param multiplier the integer multiplier.
|
|
||||||
* @return product of the multiplicand [arg] and the multiplier [multiplier].
|
|
||||||
* @author Gleb Minaev
|
|
||||||
*/
|
|
||||||
internal fun <C> Group<C>.multiplyByDoubling(arg: C, multiplier: Int): C =
|
|
||||||
if (multiplier >= 0) multiplyByDoubling(arg, multiplier.toUInt())
|
|
||||||
else multiplyByDoubling(-arg, (-multiplier).toUInt())
|
|
||||||
|
|
||||||
// FIXME: Move receiver to context receiver
|
|
||||||
/**
|
|
||||||
* Adds product of [arg] and [multiplier] to [base].
|
|
||||||
*
|
|
||||||
* @param base the augend.
|
|
||||||
* @param arg the multiplicand.
|
|
||||||
* @param multiplier the integer multiplier.
|
|
||||||
* @return sum of the augend [base] and product of the multiplicand [arg] and the multiplier [multiplier].
|
|
||||||
* @author Gleb Minaev
|
|
||||||
*/
|
|
||||||
internal fun <C> GroupOps<C>.addMultipliedByDoubling(base: C, arg: C, multiplier: Int): C =
|
|
||||||
if (multiplier >= 0) addMultipliedByDoubling(base, arg, multiplier.toUInt())
|
|
||||||
else addMultipliedByDoubling(base, -arg, (-multiplier).toUInt())
|
|
||||||
|
|
||||||
// FIXME: Move receiver to context receiver
|
|
||||||
/**
|
|
||||||
* Returns product of [arg] and integer [multiplier].
|
|
||||||
*
|
|
||||||
* This is implementation of variation of [exponentiation by squaring](https://en.wikipedia.org/wiki/Exponentiation_by_squaring)
|
|
||||||
*
|
|
||||||
* @param arg the multiplicand.
|
|
||||||
* @param multiplier the integer multiplier.
|
|
||||||
* @return product of the multiplicand [arg] and the multiplier [multiplier].
|
|
||||||
* @author Gleb Minaev
|
|
||||||
*/
|
|
||||||
internal tailrec fun <C> Group<C>.multiplyByDoubling(arg: C, multiplier: UInt): C =
|
|
||||||
when {
|
|
||||||
multiplier == 0u -> zero
|
|
||||||
multiplier == 1u -> arg
|
|
||||||
multiplier and 1u == 0u -> multiplyByDoubling(arg + arg, multiplier shr 1)
|
|
||||||
multiplier and 1u == 1u -> addMultipliedByDoubling(arg, arg + arg, multiplier shr 1)
|
|
||||||
else -> error("Error in multiplication group instant by unsigned integer: got reminder by division by 2 different from 0 and 1")
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: Move receiver to context receiver
|
|
||||||
/**
|
|
||||||
* Adds product of [arg] and [multiplier] to [base].
|
|
||||||
*
|
|
||||||
* This is implementation of variation of [exponentiation by squaring](https://en.wikipedia.org/wiki/Exponentiation_by_squaring)
|
|
||||||
*
|
|
||||||
* @param base the augend.
|
|
||||||
* @param arg the multiplicand.
|
|
||||||
* @param multiplier the integer multiplier.
|
|
||||||
* @return sum of the augend [base] and product of the multiplicand [arg] and the multiplier [multiplier].
|
|
||||||
* @author Gleb Minaev
|
|
||||||
*/
|
|
||||||
internal tailrec fun <C> GroupOps<C>.addMultipliedByDoubling(base: C, arg: C, multiplier: UInt): C =
|
|
||||||
when {
|
|
||||||
multiplier == 0u -> base
|
|
||||||
multiplier == 1u -> base + arg
|
|
||||||
multiplier and 1u == 0u -> addMultipliedByDoubling(base, arg + arg, multiplier shr 1)
|
|
||||||
multiplier and 1u == 1u -> addMultipliedByDoubling(base + arg, arg + arg, multiplier shr 1)
|
|
||||||
else -> error("Error in multiplication group instant by unsigned integer: got reminder by division by 2 different from 0 and 1")
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: Move receiver to context receiver
|
|
||||||
/**
|
|
||||||
* Raises [arg] to the integer power [exponent].
|
|
||||||
*
|
|
||||||
* @param arg the base of the power.
|
|
||||||
* @param exponent the exponent of the power.
|
|
||||||
* @return [arg] raised to the power [exponent].
|
|
||||||
* @author Gleb Minaev
|
|
||||||
*/
|
|
||||||
internal fun <C> Field<C>.exponentiateBySquaring(arg: C, exponent: Int): C =
|
|
||||||
if (exponent >= 0) exponentiateBySquaring(arg, exponent.toUInt())
|
|
||||||
else exponentiateBySquaring(one / arg, (-exponent).toUInt())
|
|
||||||
|
|
||||||
// FIXME: Move receiver to context receiver
|
|
||||||
/**
|
|
||||||
* Multiplies [base] and [arg] raised to the integer power [exponent].
|
|
||||||
*
|
|
||||||
* @param base the multiplicand.
|
|
||||||
* @param arg the base of the power.
|
|
||||||
* @param exponent the exponent of the power.
|
|
||||||
* @return product of [base] and [arg] raised to the power [exponent].
|
|
||||||
* @author Gleb Minaev
|
|
||||||
*/
|
|
||||||
internal fun <C> Field<C>.multiplyExponentiatedBySquaring(base: C, arg: C, exponent: Int): C =
|
|
||||||
if (exponent >= 0) multiplyExponentiatedBySquaring(base, arg, exponent.toUInt())
|
|
||||||
else multiplyExponentiatedBySquaring(base, one / arg, (-exponent).toUInt())
|
|
||||||
|
|
||||||
// FIXME: Move receiver to context receiver
|
// FIXME: Move receiver to context receiver
|
||||||
/**
|
/**
|
||||||
* Raises [arg] to the integer power [exponent].
|
* Raises [arg] to the integer power [exponent].
|
||||||
|
@ -1,92 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a [ListPolynomial] instance with provided [coefficients]. The collection of coefficients will be reversed
|
|
||||||
* if [reverse] parameter is true.
|
|
||||||
*/
|
|
||||||
@Suppress("FunctionName")
|
|
||||||
public fun <C> ListPolynomial(coefficients: List<C>, reverse: Boolean = false): ListPolynomial<C> =
|
|
||||||
ListPolynomial(with(coefficients) { if (reverse) reversed() else this })
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a [ListPolynomial] instance with provided [coefficients]. The collection of coefficients will be reversed
|
|
||||||
* if [reverse] parameter is true.
|
|
||||||
*/
|
|
||||||
@Suppress("FunctionName")
|
|
||||||
public fun <C> ListPolynomial(vararg coefficients: C, reverse: Boolean = false): ListPolynomial<C> =
|
|
||||||
ListPolynomial(with(coefficients) { if (reverse) reversed() else toList() })
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents [this] constant as a [ListPolynomial].
|
|
||||||
*/
|
|
||||||
public fun <C> C.asListPolynomial() : ListPolynomial<C> = ListPolynomial(listOf(this))
|
|
||||||
|
|
||||||
|
|
||||||
// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs [ListRationalFunction] instance with numerator and denominator constructed with provided
|
|
||||||
* [numeratorCoefficients] and [denominatorCoefficients]. The both collections of coefficients will be reversed if
|
|
||||||
* [reverse] parameter is true.
|
|
||||||
*/
|
|
||||||
@Suppress("FunctionName")
|
|
||||||
public fun <C> ListRationalFunction(numeratorCoefficients: List<C>, denominatorCoefficients: List<C>, reverse: Boolean = false): ListRationalFunction<C> =
|
|
||||||
ListRationalFunction<C>(
|
|
||||||
ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ),
|
|
||||||
ListPolynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } )
|
|
||||||
)
|
|
||||||
/**
|
|
||||||
* Constructs [ListRationalFunction] instance with provided [numerator] and unit denominator.
|
|
||||||
*/
|
|
||||||
@Suppress("FunctionName")
|
|
||||||
public fun <C, A: Ring<C>> A.ListRationalFunction(numerator: ListPolynomial<C>): ListRationalFunction<C> =
|
|
||||||
ListRationalFunction<C>(numerator, ListPolynomial(listOf(one)))
|
|
||||||
/**
|
|
||||||
* Constructs [ListRationalFunction] instance with provided [numerator] and unit denominator.
|
|
||||||
*/
|
|
||||||
@Suppress("FunctionName")
|
|
||||||
public fun <C, A: Ring<C>> ListRationalFunctionSpace<C, A>.ListRationalFunction(numerator: ListPolynomial<C>): ListRationalFunction<C> =
|
|
||||||
ListRationalFunction<C>(numerator, polynomialOne)
|
|
||||||
/**
|
|
||||||
* Constructs [ListRationalFunction] instance with numerator constructed with provided [numeratorCoefficients] and unit
|
|
||||||
* denominator. The collection of numerator coefficients will be reversed if [reverse] parameter is true.
|
|
||||||
*/
|
|
||||||
@Suppress("FunctionName")
|
|
||||||
public fun <C, A: Ring<C>> A.ListRationalFunction(numeratorCoefficients: List<C>, reverse: Boolean = false): ListRationalFunction<C> =
|
|
||||||
ListRationalFunction<C>(
|
|
||||||
ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ),
|
|
||||||
ListPolynomial(listOf(one))
|
|
||||||
)
|
|
||||||
/**
|
|
||||||
* Constructs [ListRationalFunction] instance with numerator constructed with provided [numeratorCoefficients] and unit
|
|
||||||
* denominator. The collection of numerator coefficients will be reversed if [reverse] parameter is true.
|
|
||||||
*/
|
|
||||||
@Suppress("FunctionName")
|
|
||||||
public fun <C, A: Ring<C>> ListRationalFunctionSpace<C, A>.ListRationalFunction(numeratorCoefficients: List<C>, reverse: Boolean = false): ListRationalFunction<C> =
|
|
||||||
ListRationalFunction<C>(
|
|
||||||
ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ),
|
|
||||||
polynomialOne
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents [this] constant as a rational function.
|
|
||||||
*/ // FIXME: When context receivers will be ready, delete this function and uncomment the following two
|
|
||||||
public fun <C, A: Ring<C>> C.asListRationalFunction(ring: A) : ListRationalFunction<C> = ring.ListRationalFunction(asListPolynomial())
|
|
||||||
///**
|
|
||||||
// * Represents [this] constant as a rational function.
|
|
||||||
// */
|
|
||||||
//context(A)
|
|
||||||
//public fun <C, A: Ring<C>> C.asListRationalFunction() : ListRationalFunction<C> = ListRationalFunction(asListPolynomial())
|
|
||||||
///**
|
|
||||||
// * Represents [this] constant as a rational function.
|
|
||||||
// */
|
|
||||||
//context(ListRationalFunctionSpace<C, A>)
|
|
||||||
//public fun <C, A: Ring<C>> C.asListRationalFunction() : ListRationalFunction<C> = ListRationalFunction(asListPolynomial())
|
|
@ -1,255 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.misc.UnstableKMathAPI
|
|
||||||
import space.kscience.kmath.operations.*
|
|
||||||
import kotlin.contracts.InvocationKind
|
|
||||||
import kotlin.contracts.contract
|
|
||||||
import kotlin.math.max
|
|
||||||
import kotlin.math.pow
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a [ListPolynomialSpace] over a received ring.
|
|
||||||
*/
|
|
||||||
public inline val <C, A : Ring<C>> A.listPolynomialSpace: ListPolynomialSpace<C, A>
|
|
||||||
get() = ListPolynomialSpace(this)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a [ListPolynomialSpace]'s scope over a received ring.
|
|
||||||
*/ // TODO: When context will be ready move [ListPolynomialSpace] and add [A] to context receivers of [block]
|
|
||||||
public inline fun <C, A : Ring<C>, R> A.listPolynomialSpace(block: ListPolynomialSpace<C, A>.() -> R): R {
|
|
||||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
|
||||||
return ListPolynomialSpace(this).block()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a [ScalableListPolynomialSpace] over a received scalable ring.
|
|
||||||
*/
|
|
||||||
public inline val <C, A> A.scalableListPolynomialSpace: ScalableListPolynomialSpace<C, A> where A : Ring<C>, A : ScaleOperations<C>
|
|
||||||
get() = ScalableListPolynomialSpace(this)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a [ScalableListPolynomialSpace]'s scope over a received scalable ring.
|
|
||||||
*/ // TODO: When context will be ready move [ListPolynomialSpace] and add [A] to context receivers of [block]
|
|
||||||
public inline fun <C, A, R> A.scalableListPolynomialSpace(block: ScalableListPolynomialSpace<C, A>.() -> R): R where A : Ring<C>, A : ScaleOperations<C> {
|
|
||||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
|
||||||
return ScalableListPolynomialSpace(this).block()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a [ListRationalFunctionSpace] over a received ring.
|
|
||||||
*/
|
|
||||||
public inline val <C, A : Ring<C>> A.listRationalFunctionSpace: ListRationalFunctionSpace<C, A>
|
|
||||||
get() = ListRationalFunctionSpace(this)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a [ListRationalFunctionSpace]'s scope over a received ring.
|
|
||||||
*/ // TODO: When context will be ready move [ListRationalFunctionSpace] and add [A] to context receivers of [block]
|
|
||||||
public inline fun <C, A : Ring<C>, R> A.listRationalFunctionSpace(block: ListRationalFunctionSpace<C, A>.() -> R): R {
|
|
||||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
|
||||||
return ListRationalFunctionSpace(this).block()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Evaluates value of [this] Double polynomial on provided Double argument.
|
|
||||||
*/
|
|
||||||
public fun ListPolynomial<Double>.substitute(arg: Double): Double =
|
|
||||||
coefficients.reduceIndexedOrNull { index, acc, c ->
|
|
||||||
acc + c * arg.pow(index)
|
|
||||||
} ?: .0
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Evaluates value of [this] polynomial on provided argument.
|
|
||||||
*
|
|
||||||
* It is an implementation of [Horner's method](https://en.wikipedia.org/wiki/Horner%27s_method).
|
|
||||||
*/
|
|
||||||
public fun <C> ListPolynomial<C>.substitute(ring: Ring<C>, arg: C): C = ring {
|
|
||||||
if (coefficients.isEmpty()) return zero
|
|
||||||
var result: C = coefficients.last()
|
|
||||||
for (j in coefficients.size - 2 downTo 0) {
|
|
||||||
result = (arg * result) + coefficients[j]
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Substitutes provided polynomial [arg] into [this] polynomial.
|
|
||||||
*
|
|
||||||
* It is an implementation of [Horner's method](https://en.wikipedia.org/wiki/Horner%27s_method).
|
|
||||||
*/ // TODO: To optimize boxing
|
|
||||||
public fun <C> ListPolynomial<C>.substitute(ring: Ring<C>, arg: ListPolynomial<C>) : ListPolynomial<C> =
|
|
||||||
ring.listPolynomialSpace {
|
|
||||||
if (coefficients.isEmpty()) return zero
|
|
||||||
var result: ListPolynomial<C> = coefficients.last().asPolynomial()
|
|
||||||
for (j in coefficients.size - 2 downTo 0) {
|
|
||||||
result = (arg * result) + coefficients[j]
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Substitutes provided rational function [arg] into [this] polynomial.
|
|
||||||
*
|
|
||||||
* It is an implementation of [Horner's method](https://en.wikipedia.org/wiki/Horner%27s_method).
|
|
||||||
*/ // TODO: To optimize boxing
|
|
||||||
public fun <C> ListPolynomial<C>.substitute(ring: Ring<C>, arg: ListRationalFunction<C>) : ListRationalFunction<C> =
|
|
||||||
ring.listRationalFunctionSpace {
|
|
||||||
if (coefficients.isEmpty()) return zero
|
|
||||||
var result: ListRationalFunction<C> = coefficients.last().asRationalFunction()
|
|
||||||
for (j in coefficients.size - 2 downTo 0) {
|
|
||||||
result = (arg * result) + coefficients[j]
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Evaluates value of [this] Double rational function in provided Double argument.
|
|
||||||
*/
|
|
||||||
public fun ListRationalFunction<Double>.substitute(arg: Double): Double =
|
|
||||||
numerator.substitute(arg) / denominator.substitute(arg)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Evaluates value of [this] polynomial for provided argument.
|
|
||||||
*
|
|
||||||
* It is an implementation of [Horner's method](https://en.wikipedia.org/wiki/Horner%27s_method).
|
|
||||||
*/
|
|
||||||
public fun <C> ListRationalFunction<C>.substitute(ring: Field<C>, arg: C): C = ring {
|
|
||||||
numerator.substitute(ring, arg) / denominator.substitute(ring, arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Substitutes provided polynomial [arg] into [this] rational function.
|
|
||||||
*/ // TODO: To optimize boxing
|
|
||||||
public fun <C> ListRationalFunction<C>.substitute(ring: Ring<C>, arg: ListPolynomial<C>) : ListRationalFunction<C> =
|
|
||||||
ring.listRationalFunctionSpace {
|
|
||||||
numerator.substitute(ring, arg) / denominator.substitute(ring, arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Substitutes provided rational function [arg] into [this] rational function.
|
|
||||||
*/ // TODO: To optimize boxing
|
|
||||||
public fun <C> ListRationalFunction<C>.substitute(ring: Ring<C>, arg: ListRationalFunction<C>) : ListRationalFunction<C> =
|
|
||||||
ring.listRationalFunctionSpace {
|
|
||||||
numerator.substitute(ring, arg) / denominator.substitute(ring, arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represent [this] polynomial as a regular context-less function.
|
|
||||||
*/
|
|
||||||
public fun <C, A : Ring<C>> ListPolynomial<C>.asFunctionOver(ring: A): (C) -> C = { substitute(ring, it) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represent [this] polynomial as a regular context-less function.
|
|
||||||
*/
|
|
||||||
public fun <C, A : Ring<C>> ListPolynomial<C>.asFunctionOfConstantOver(ring: A): (C) -> C = { substitute(ring, it) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represent [this] polynomial as a regular context-less function.
|
|
||||||
*/
|
|
||||||
public fun <C, A : Ring<C>> ListPolynomial<C>.asFunctionOfPolynomialOver(ring: A): (ListPolynomial<C>) -> ListPolynomial<C> = { substitute(ring, it) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represent [this] polynomial as a regular context-less function.
|
|
||||||
*/
|
|
||||||
public fun <C, A : Ring<C>> ListPolynomial<C>.asFunctionOfRationalFunctionOver(ring: A): (ListRationalFunction<C>) -> ListRationalFunction<C> = { substitute(ring, it) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represent [this] rational function as a regular context-less function.
|
|
||||||
*/
|
|
||||||
public fun <C, A : Field<C>> ListRationalFunction<C>.asFunctionOver(ring: A): (C) -> C = { substitute(ring, it) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represent [this] rational function as a regular context-less function.
|
|
||||||
*/
|
|
||||||
public fun <C, A : Field<C>> ListRationalFunction<C>.asFunctionOfConstantOver(ring: A): (C) -> C = { substitute(ring, it) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represent [this] rational function as a regular context-less function.
|
|
||||||
*/
|
|
||||||
public fun <C, A : Ring<C>> ListRationalFunction<C>.asFunctionOfPolynomialOver(ring: A): (ListPolynomial<C>) -> ListRationalFunction<C> = { substitute(ring, it) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represent [this] rational function as a regular context-less function.
|
|
||||||
*/
|
|
||||||
public fun <C, A : Ring<C>> ListRationalFunction<C>.asFunctionOfRationalFunctionOver(ring: A): (ListRationalFunction<C>) -> ListRationalFunction<C> = { substitute(ring, it) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns algebraic derivative of received polynomial.
|
|
||||||
*/
|
|
||||||
@UnstableKMathAPI
|
|
||||||
public fun <C, A> ListPolynomial<C>.derivative(
|
|
||||||
ring: A,
|
|
||||||
): ListPolynomial<C> where A : Ring<C>, A : NumericAlgebra<C> = ring {
|
|
||||||
ListPolynomial(
|
|
||||||
buildList(max(0, coefficients.size - 1)) {
|
|
||||||
for (deg in 1 .. coefficients.lastIndex) add(number(deg) * coefficients[deg])
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns algebraic derivative of received polynomial of specified [order]. The [order] should be non-negative integer.
|
|
||||||
*/
|
|
||||||
@UnstableKMathAPI
|
|
||||||
public fun <C, A> ListPolynomial<C>.nthDerivative(
|
|
||||||
ring: A,
|
|
||||||
order: Int,
|
|
||||||
): ListPolynomial<C> where A : Ring<C>, A : NumericAlgebra<C> = ring {
|
|
||||||
require(order >= 0) { "Order of derivative must be non-negative" }
|
|
||||||
ListPolynomial(
|
|
||||||
buildList(max(0, coefficients.size - order)) {
|
|
||||||
for (deg in order.. coefficients.lastIndex)
|
|
||||||
add((deg - order + 1 .. deg).fold(coefficients[deg]) { acc, d -> acc * number(d) })
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns algebraic antiderivative of received polynomial.
|
|
||||||
*/
|
|
||||||
@UnstableKMathAPI
|
|
||||||
public fun <C, A> ListPolynomial<C>.antiderivative(
|
|
||||||
ring: A,
|
|
||||||
): ListPolynomial<C> where A : Field<C>, A : NumericAlgebra<C> = ring {
|
|
||||||
ListPolynomial(
|
|
||||||
buildList(coefficients.size + 1) {
|
|
||||||
add(zero)
|
|
||||||
coefficients.mapIndexedTo(this) { index, t -> t / number(index + 1) }
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns algebraic antiderivative of received polynomial of specified [order]. The [order] should be non-negative integer.
|
|
||||||
*/
|
|
||||||
@UnstableKMathAPI
|
|
||||||
public fun <C, A> ListPolynomial<C>.nthAntiderivative(
|
|
||||||
ring: A,
|
|
||||||
order: Int,
|
|
||||||
): ListPolynomial<C> where A : Field<C>, A : NumericAlgebra<C> = ring {
|
|
||||||
require(order >= 0) { "Order of antiderivative must be non-negative" }
|
|
||||||
ListPolynomial(
|
|
||||||
buildList(coefficients.size + order) {
|
|
||||||
repeat(order) { add(zero) }
|
|
||||||
coefficients.mapIndexedTo(this) { index, c -> (1..order).fold(c) { acc, i -> acc / number(index + i) } }
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Computes a definite integral of [this] polynomial in the specified [range].
|
|
||||||
*/
|
|
||||||
@UnstableKMathAPI
|
|
||||||
public fun <C : Comparable<C>> ListPolynomial<C>.integrate(
|
|
||||||
ring: Field<C>,
|
|
||||||
range: ClosedRange<C>,
|
|
||||||
): C = ring {
|
|
||||||
val antiderivative = antiderivative(ring)
|
|
||||||
antiderivative.substitute(ring, range.endInclusive) - antiderivative.substitute(ring, range.start)
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Marks declarations that give access to internal entities of polynomials delicate structure. Thus, it allows to
|
|
||||||
* optimize performance a bit by skipping standard steps, but such skips may cause critical errors if something is
|
|
||||||
* implemented badly. Make sure you fully read and understand documentation and don't break internal contracts.
|
|
||||||
*/
|
|
||||||
@RequiresOptIn(
|
|
||||||
message = "This declaration gives access to delicate internal structure of polynomials. " +
|
|
||||||
"It allows to optimize performance by skipping unnecessary arguments check. " +
|
|
||||||
"But at the same time makes it easy to make a mistake " +
|
|
||||||
"that will cause wrong computation result or even runtime error. " +
|
|
||||||
"Make sure you fully read and understand documentation.",
|
|
||||||
level = RequiresOptIn.Level.ERROR
|
|
||||||
)
|
|
||||||
public annotation class DelicatePolynomialAPI
|
|
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a [Polynomial] instance with provided [coefficients]. The collection of coefficients will be reversed
|
||||||
|
* if [reverse] parameter is true.
|
||||||
|
*/
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
public fun <C> ListPolynomial(coefficients: List<C>, reverse: Boolean = false): Polynomial<C> =
|
||||||
|
Polynomial(with(coefficients) { if (reverse) reversed() else this })
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a [Polynomial] instance with provided [coefficients]. The collection of coefficients will be reversed
|
||||||
|
* if [reverse] parameter is true.
|
||||||
|
*/
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
public fun <C> ListPolynomial(vararg coefficients: C, reverse: Boolean = false): Polynomial<C> =
|
||||||
|
Polynomial(with(coefficients) { if (reverse) reversed() else toList() })
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents [this] constant as a [Polynomial].
|
||||||
|
*/
|
||||||
|
public fun <C> C.asListPolynomial() : Polynomial<C> = Polynomial(listOf(this))
|
@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* 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.misc.UnstableKMathAPI
|
||||||
|
import space.kscience.kmath.operations.*
|
||||||
|
import kotlin.contracts.InvocationKind
|
||||||
|
import kotlin.contracts.contract
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlin.math.pow
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a [ListPolynomialSpace] over a received ring.
|
||||||
|
*/
|
||||||
|
public inline val <C, A : Ring<C>> A.listPolynomialSpace: ListPolynomialSpace<C, A>
|
||||||
|
get() = ListPolynomialSpace(this)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a [ListPolynomialSpace]'s scope over a received ring.
|
||||||
|
*/ // TODO: When context will be ready move [ListPolynomialSpace] and add [A] to context receivers of [block]
|
||||||
|
public inline fun <C, A : Ring<C>, R> A.listPolynomialSpace(block: ListPolynomialSpace<C, A>.() -> R): R {
|
||||||
|
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||||
|
return ListPolynomialSpace(this).block()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a [ScalableListPolynomialSpace] over a received scalable ring.
|
||||||
|
*/
|
||||||
|
public inline val <C, A> A.scalableListPolynomialSpace: ScalableListPolynomialSpace<C, A> where A : Ring<C>, A : ScaleOperations<C>
|
||||||
|
get() = ScalableListPolynomialSpace(this)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a [ScalableListPolynomialSpace]'s scope over a received scalable ring.
|
||||||
|
*/ // TODO: When context will be ready move [ListPolynomialSpace] and add [A] to context receivers of [block]
|
||||||
|
public inline fun <C, A, R> A.scalableListPolynomialSpace(block: ScalableListPolynomialSpace<C, A>.() -> R): R where A : Ring<C>, A : ScaleOperations<C> {
|
||||||
|
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||||
|
return ScalableListPolynomialSpace(this).block()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates value of [this] Double polynomial on provided Double argument.
|
||||||
|
*/
|
||||||
|
public fun Polynomial<Double>.substitute(arg: Double): Double =
|
||||||
|
coefficients.reduceIndexedOrNull { index, acc, c ->
|
||||||
|
acc + c * arg.pow(index)
|
||||||
|
} ?: .0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates value of [this] polynomial on provided argument.
|
||||||
|
*
|
||||||
|
* It is an implementation of [Horner's method](https://en.wikipedia.org/wiki/Horner%27s_method).
|
||||||
|
*/
|
||||||
|
public fun <C> Polynomial<C>.substitute(ring: Ring<C>, arg: C): C = ring {
|
||||||
|
if (coefficients.isEmpty()) return zero
|
||||||
|
var result: C = coefficients.last()
|
||||||
|
for (j in coefficients.size - 2 downTo 0) {
|
||||||
|
result = (arg * result) + coefficients[j]
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represent [this] polynomial as a regular context-less function.
|
||||||
|
*/
|
||||||
|
public fun <C, A : Ring<C>> Polynomial<C>.asFunctionOver(ring: A): (C) -> C = { substitute(ring, it) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns algebraic derivative of received polynomial.
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
public fun <C, A> Polynomial<C>.derivative(
|
||||||
|
ring: A,
|
||||||
|
): Polynomial<C> where A : Ring<C>, A : NumericAlgebra<C> = ring {
|
||||||
|
Polynomial(
|
||||||
|
buildList(max(0, coefficients.size - 1)) {
|
||||||
|
for (deg in 1 .. coefficients.lastIndex) add(number(deg) * coefficients[deg])
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns algebraic antiderivative of received polynomial.
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
public fun <C, A> Polynomial<C>.antiderivative(
|
||||||
|
ring: A,
|
||||||
|
): Polynomial<C> where A : Field<C>, A : NumericAlgebra<C> = ring {
|
||||||
|
Polynomial(
|
||||||
|
buildList(coefficients.size + 1) {
|
||||||
|
add(zero)
|
||||||
|
coefficients.mapIndexedTo(this) { index, t -> t / number(index + 1) }
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes a definite integral of [this] polynomial in the specified [range].
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
public fun <C : Comparable<C>> Polynomial<C>.integrate(
|
||||||
|
ring: Field<C>,
|
||||||
|
range: ClosedRange<C>,
|
||||||
|
): C {
|
||||||
|
val antiderivative = antiderivative(ring)
|
||||||
|
return ring { antiderivative.substitute(ring, range.endInclusive) - antiderivative.substitute(ring, range.start) }
|
||||||
|
}
|
@ -26,286 +26,6 @@ object ExprRing : Field<Expr> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class AlgebraicStubTest {
|
class AlgebraicStubTest {
|
||||||
@Test
|
|
||||||
fun test_addMultipliedBySquaring_for_UInt() {
|
|
||||||
ExprRing {
|
|
||||||
assertEquals(
|
|
||||||
"57",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), 0u).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, 0u)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 + 179)",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), 1u).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, 1u)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 + (179 + 179))",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), 2u).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, 2u)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((57 + 179) + (179 + 179))",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), 3u).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, 3u)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 + ((179 + 179) + (179 + 179)))",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), 4u).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, 4u)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((57 + 179) + ((179 + 179) + (179 + 179)))",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), 5u).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, 5u)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((57 + (179 + 179)) + ((179 + 179) + (179 + 179)))",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), 6u).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, 6u)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(((57 + 179) + (179 + 179)) + ((179 + 179) + (179 + 179)))",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), 7u).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, 7u)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 + (((179 + 179) + (179 + 179)) + ((179 + 179) + (179 + 179))))",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), 8u).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, 8u)"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_multiplyBySquaring_for_UInt() {
|
|
||||||
ExprRing {
|
|
||||||
assertEquals(
|
|
||||||
"0",
|
|
||||||
multiplyByDoubling(Expr("57"), 0u).expr,
|
|
||||||
"tried multiplyBySquaring(57, 0u)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"57",
|
|
||||||
multiplyByDoubling(Expr("57"), 1u).expr,
|
|
||||||
"tried multiplyBySquaring(57, 1u)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 + 57)",
|
|
||||||
multiplyByDoubling(Expr("57"), 2u).expr,
|
|
||||||
"tried multiplyBySquaring(57, 2u)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 + (57 + 57))",
|
|
||||||
multiplyByDoubling(Expr("57"), 3u).expr,
|
|
||||||
"tried multiplyBySquaring(57, 3u)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((57 + 57) + (57 + 57))",
|
|
||||||
multiplyByDoubling(Expr("57"), 4u).expr,
|
|
||||||
"tried multiplyBySquaring(57, 4u)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 + ((57 + 57) + (57 + 57)))",
|
|
||||||
multiplyByDoubling(Expr("57"), 5u).expr,
|
|
||||||
"tried multiplyBySquaring(57, 5u)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((57 + 57) + ((57 + 57) + (57 + 57)))",
|
|
||||||
multiplyByDoubling(Expr("57"), 6u).expr,
|
|
||||||
"tried multiplyBySquaring(57, 6u)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((57 + (57 + 57)) + ((57 + 57) + (57 + 57)))",
|
|
||||||
multiplyByDoubling(Expr("57"), 7u).expr,
|
|
||||||
"tried multiplyBySquaring(57, 7u)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(((57 + 57) + (57 + 57)) + ((57 + 57) + (57 + 57)))",
|
|
||||||
multiplyByDoubling(Expr("57"), 8u).expr,
|
|
||||||
"tried multiplyBySquaring(57, 8u)"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_addMultipliedBySquaring_for_Int() {
|
|
||||||
ExprRing {
|
|
||||||
assertEquals(
|
|
||||||
"57",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), 0).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, 0)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 + 179)",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), 1).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, 1)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 + -179)",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), -1).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, -1)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 + (179 + 179))",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), 2).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, 2)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 + (-179 + -179))",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), -2).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, -2)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((57 + 179) + (179 + 179))",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), 3).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, 3)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((57 + -179) + (-179 + -179))",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), -3).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, -3)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 + ((179 + 179) + (179 + 179)))",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), 4).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, 4)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 + ((-179 + -179) + (-179 + -179)))",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), -4).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, -4)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((57 + 179) + ((179 + 179) + (179 + 179)))",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), 5).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, 5)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((57 + -179) + ((-179 + -179) + (-179 + -179)))",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), -5).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, -5)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((57 + (179 + 179)) + ((179 + 179) + (179 + 179)))",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), 6).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, 6)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((57 + (-179 + -179)) + ((-179 + -179) + (-179 + -179)))",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), -6).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, -6)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(((57 + 179) + (179 + 179)) + ((179 + 179) + (179 + 179)))",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), 7).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, 7)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(((57 + -179) + (-179 + -179)) + ((-179 + -179) + (-179 + -179)))",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), -7).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, -7)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 + (((179 + 179) + (179 + 179)) + ((179 + 179) + (179 + 179))))",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), 8).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, 8)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 + (((-179 + -179) + (-179 + -179)) + ((-179 + -179) + (-179 + -179))))",
|
|
||||||
addMultipliedByDoubling(Expr("57"), Expr("179"), -8).expr,
|
|
||||||
"tried addMultipliedBySquaring(57, 179, -8)"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_multiplyBySquaring_for_Int() {
|
|
||||||
ExprRing {
|
|
||||||
assertEquals(
|
|
||||||
"0",
|
|
||||||
multiplyByDoubling(Expr("57"), 0).expr,
|
|
||||||
"tried multiplyBySquaring(57, 0)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"57",
|
|
||||||
multiplyByDoubling(Expr("57"), 1).expr,
|
|
||||||
"tried multiplyBySquaring(57, 1)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"-57",
|
|
||||||
multiplyByDoubling(Expr("57"), -1).expr,
|
|
||||||
"tried multiplyBySquaring(57, -1)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 + 57)",
|
|
||||||
multiplyByDoubling(Expr("57"), 2).expr,
|
|
||||||
"tried multiplyBySquaring(57, 2)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(-57 + -57)",
|
|
||||||
multiplyByDoubling(Expr("57"), -2).expr,
|
|
||||||
"tried multiplyBySquaring(57, -2)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 + (57 + 57))",
|
|
||||||
multiplyByDoubling(Expr("57"), 3).expr,
|
|
||||||
"tried multiplyBySquaring(57, 3)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(-57 + (-57 + -57))",
|
|
||||||
multiplyByDoubling(Expr("57"), -3).expr,
|
|
||||||
"tried multiplyBySquaring(57, -3)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((57 + 57) + (57 + 57))",
|
|
||||||
multiplyByDoubling(Expr("57"), 4).expr,
|
|
||||||
"tried multiplyBySquaring(57, 4)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((-57 + -57) + (-57 + -57))",
|
|
||||||
multiplyByDoubling(Expr("57"), -4).expr,
|
|
||||||
"tried multiplyBySquaring(57, -4)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 + ((57 + 57) + (57 + 57)))",
|
|
||||||
multiplyByDoubling(Expr("57"), 5).expr,
|
|
||||||
"tried multiplyBySquaring(57, 5)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(-57 + ((-57 + -57) + (-57 + -57)))",
|
|
||||||
multiplyByDoubling(Expr("57"), -5).expr,
|
|
||||||
"tried multiplyBySquaring(57, -5)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((57 + 57) + ((57 + 57) + (57 + 57)))",
|
|
||||||
multiplyByDoubling(Expr("57"), 6).expr,
|
|
||||||
"tried multiplyBySquaring(57, 6)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((-57 + -57) + ((-57 + -57) + (-57 + -57)))",
|
|
||||||
multiplyByDoubling(Expr("57"), -6).expr,
|
|
||||||
"tried multiplyBySquaring(57, -6)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((57 + (57 + 57)) + ((57 + 57) + (57 + 57)))",
|
|
||||||
multiplyByDoubling(Expr("57"), 7).expr,
|
|
||||||
"tried multiplyBySquaring(57, 7)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((-57 + (-57 + -57)) + ((-57 + -57) + (-57 + -57)))",
|
|
||||||
multiplyByDoubling(Expr("57"), -7).expr,
|
|
||||||
"tried multiplyBySquaring(57, -7)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(((57 + 57) + (57 + 57)) + ((57 + 57) + (57 + 57)))",
|
|
||||||
multiplyByDoubling(Expr("57"), 8).expr,
|
|
||||||
"tried multiplyBySquaring(57, 8)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(((-57 + -57) + (-57 + -57)) + ((-57 + -57) + (-57 + -57)))",
|
|
||||||
multiplyByDoubling(Expr("57"), -8).expr,
|
|
||||||
"tried multiplyBySquaring(57, -8)"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Test
|
@Test
|
||||||
fun test_multiplyExponentiationBySquaring_for_UInt() {
|
fun test_multiplyExponentiationBySquaring_for_UInt() {
|
||||||
ExprRing {
|
ExprRing {
|
||||||
@ -406,184 +126,4 @@ class AlgebraicStubTest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Test
|
|
||||||
fun test_multiplyExponentiationBySquaring_for_Int() {
|
|
||||||
ExprRing {
|
|
||||||
assertEquals(
|
|
||||||
"57",
|
|
||||||
multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 0).expr,
|
|
||||||
"tried multiplyExponentiationBySquaring(57, 179, 0)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 * 179)",
|
|
||||||
multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 1).expr,
|
|
||||||
"tried multiplyExponentiationBySquaring(57, 179, 1)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 * (1 / 179))",
|
|
||||||
multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), -1).expr,
|
|
||||||
"tried multiplyExponentiationBySquaring(57, 179, -1)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 * (179 * 179))",
|
|
||||||
multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 2).expr,
|
|
||||||
"tried multiplyExponentiationBySquaring(57, 179, 2)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 * ((1 / 179) * (1 / 179)))",
|
|
||||||
multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), -2).expr,
|
|
||||||
"tried multiplyExponentiationBySquaring(57, 179, -2)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((57 * 179) * (179 * 179))",
|
|
||||||
multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 3).expr,
|
|
||||||
"tried multiplyExponentiationBySquaring(57, 179, 3)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((57 * (1 / 179)) * ((1 / 179) * (1 / 179)))",
|
|
||||||
multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), -3).expr,
|
|
||||||
"tried multiplyExponentiationBySquaring(57, 179, -3)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 * ((179 * 179) * (179 * 179)))",
|
|
||||||
multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 4).expr,
|
|
||||||
"tried multiplyExponentiationBySquaring(57, 179, 4)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 * (((1 / 179) * (1 / 179)) * ((1 / 179) * (1 / 179))))",
|
|
||||||
multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), -4).expr,
|
|
||||||
"tried multiplyExponentiationBySquaring(57, 179, -4)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((57 * 179) * ((179 * 179) * (179 * 179)))",
|
|
||||||
multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 5).expr,
|
|
||||||
"tried multiplyExponentiationBySquaring(57, 179, 5)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((57 * (1 / 179)) * (((1 / 179) * (1 / 179)) * ((1 / 179) * (1 / 179))))",
|
|
||||||
multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), -5).expr,
|
|
||||||
"tried multiplyExponentiationBySquaring(57, 179, -5)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((57 * (179 * 179)) * ((179 * 179) * (179 * 179)))",
|
|
||||||
multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 6).expr,
|
|
||||||
"tried multiplyExponentiationBySquaring(57, 179, 6)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((57 * ((1 / 179) * (1 / 179))) * (((1 / 179) * (1 / 179)) * ((1 / 179) * (1 / 179))))",
|
|
||||||
multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), -6).expr,
|
|
||||||
"tried multiplyExponentiationBySquaring(57, 179, -6)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(((57 * 179) * (179 * 179)) * ((179 * 179) * (179 * 179)))",
|
|
||||||
multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 7).expr,
|
|
||||||
"tried multiplyExponentiationBySquaring(57, 179, 7)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(((57 * (1 / 179)) * ((1 / 179) * (1 / 179))) * (((1 / 179) * (1 / 179)) * ((1 / 179) * (1 / 179))))",
|
|
||||||
multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), -7).expr,
|
|
||||||
"tried multiplyExponentiationBySquaring(57, 179, -7)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 * (((179 * 179) * (179 * 179)) * ((179 * 179) * (179 * 179))))",
|
|
||||||
multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), 8).expr,
|
|
||||||
"tried multiplyExponentiationBySquaring(57, 179, 8)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 * ((((1 / 179) * (1 / 179)) * ((1 / 179) * (1 / 179))) * (((1 / 179) * (1 / 179)) * ((1 / 179) * (1 / 179)))))",
|
|
||||||
multiplyExponentiatedBySquaring(Expr("57"), Expr("179"), -8).expr,
|
|
||||||
"tried multiplyExponentiationBySquaring(57, 179, -8)"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_exponentiationBySquaring_for_Int() {
|
|
||||||
ExprRing {
|
|
||||||
assertEquals(
|
|
||||||
"0",
|
|
||||||
exponentiateBySquaring(Expr("57"), 0).expr,
|
|
||||||
"tried exponentiationBySquaring(57, 0)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"57",
|
|
||||||
exponentiateBySquaring(Expr("57"), 1).expr,
|
|
||||||
"tried exponentiationBySquaring(57, 1)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(1 / 57)",
|
|
||||||
exponentiateBySquaring(Expr("57"), -1).expr,
|
|
||||||
"tried exponentiationBySquaring(57, -1)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 * 57)",
|
|
||||||
exponentiateBySquaring(Expr("57"), 2).expr,
|
|
||||||
"tried exponentiationBySquaring(57, 2)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((1 / 57) * (1 / 57))",
|
|
||||||
exponentiateBySquaring(Expr("57"), -2).expr,
|
|
||||||
"tried exponentiationBySquaring(57, -2)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 * (57 * 57))",
|
|
||||||
exponentiateBySquaring(Expr("57"), 3).expr,
|
|
||||||
"tried exponentiationBySquaring(57, 3)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((1 / 57) * ((1 / 57) * (1 / 57)))",
|
|
||||||
exponentiateBySquaring(Expr("57"), -3).expr,
|
|
||||||
"tried exponentiationBySquaring(57, -3)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((57 * 57) * (57 * 57))",
|
|
||||||
exponentiateBySquaring(Expr("57"), 4).expr,
|
|
||||||
"tried exponentiationBySquaring(57, 4)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(((1 / 57) * (1 / 57)) * ((1 / 57) * (1 / 57)))",
|
|
||||||
exponentiateBySquaring(Expr("57"), -4).expr,
|
|
||||||
"tried exponentiationBySquaring(57, -4)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(57 * ((57 * 57) * (57 * 57)))",
|
|
||||||
exponentiateBySquaring(Expr("57"), 5).expr,
|
|
||||||
"tried exponentiationBySquaring(57, 5)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((1 / 57) * (((1 / 57) * (1 / 57)) * ((1 / 57) * (1 / 57))))",
|
|
||||||
exponentiateBySquaring(Expr("57"), -5).expr,
|
|
||||||
"tried exponentiationBySquaring(57, -5)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((57 * 57) * ((57 * 57) * (57 * 57)))",
|
|
||||||
exponentiateBySquaring(Expr("57"), 6).expr,
|
|
||||||
"tried exponentiationBySquaring(57, 6)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(((1 / 57) * (1 / 57)) * (((1 / 57) * (1 / 57)) * ((1 / 57) * (1 / 57))))",
|
|
||||||
exponentiateBySquaring(Expr("57"), -6).expr,
|
|
||||||
"tried exponentiationBySquaring(57, -6)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((57 * (57 * 57)) * ((57 * 57) * (57 * 57)))",
|
|
||||||
exponentiateBySquaring(Expr("57"), 7).expr,
|
|
||||||
"tried exponentiationBySquaring(57, 7)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(((1 / 57) * ((1 / 57) * (1 / 57))) * (((1 / 57) * (1 / 57)) * ((1 / 57) * (1 / 57))))",
|
|
||||||
exponentiateBySquaring(Expr("57"), -7).expr,
|
|
||||||
"tried exponentiationBySquaring(57, -7)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"(((57 * 57) * (57 * 57)) * ((57 * 57) * (57 * 57)))",
|
|
||||||
exponentiateBySquaring(Expr("57"), 8).expr,
|
|
||||||
"tried exponentiationBySquaring(57, 8)"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
"((((1 / 57) * (1 / 57)) * ((1 / 57) * (1 / 57))) * (((1 / 57) * (1 / 57)) * ((1 / 57) * (1 / 57))))",
|
|
||||||
exponentiateBySquaring(Expr("57"), -8).expr,
|
|
||||||
"tried exponentiationBySquaring(57, -8)"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -7,252 +7,11 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.functions
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
import space.kscience.kmath.functions.testUtils.IntModuloRing
|
import space.kscience.kmath.functions.testUtils.*
|
||||||
import space.kscience.kmath.functions.testUtils.ListPolynomial
|
|
||||||
import space.kscience.kmath.functions.testUtils.Rational
|
|
||||||
import space.kscience.kmath.functions.testUtils.RationalField
|
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
|
|
||||||
class ListPolynomialTest {
|
class ListPolynomialTest {
|
||||||
@Test
|
|
||||||
fun test_Polynomial_Int_plus() {
|
|
||||||
RationalField.listPolynomialSpace {
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)),
|
|
||||||
ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + -3,
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0)),
|
|
||||||
ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + 2,
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0)),
|
|
||||||
ListPolynomial(Rational(-2)) + 2,
|
|
||||||
"test 3"
|
|
||||||
)
|
|
||||||
val polynomial_4 = ListPolynomial<Rational>()
|
|
||||||
assertSame(
|
|
||||||
polynomial_4,
|
|
||||||
polynomial_4 + 0,
|
|
||||||
"test 4"
|
|
||||||
)
|
|
||||||
val polynomial_5 = ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7))
|
|
||||||
assertSame(
|
|
||||||
polynomial_5,
|
|
||||||
polynomial_5 + 0,
|
|
||||||
"test 5"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-1), Rational(0), Rational(0), Rational(0)),
|
|
||||||
ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + 1,
|
|
||||||
"test 6"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-1)),
|
|
||||||
ListPolynomial(Rational(-2)) + 1,
|
|
||||||
"test 7"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(2)),
|
|
||||||
ListPolynomial<Rational>() + 2,
|
|
||||||
"test 8"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_Polynomial_Int_minus() {
|
|
||||||
RationalField.listPolynomialSpace {
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)),
|
|
||||||
ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - -3,
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0)),
|
|
||||||
ListPolynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - 2,
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0)),
|
|
||||||
ListPolynomial(Rational(2)) - 2,
|
|
||||||
"test 3"
|
|
||||||
)
|
|
||||||
val polynomial_4 = ListPolynomial<Rational>()
|
|
||||||
assertSame(
|
|
||||||
polynomial_4,
|
|
||||||
polynomial_4 - 0,
|
|
||||||
"test 4"
|
|
||||||
)
|
|
||||||
val polynomial_5 = ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7))
|
|
||||||
assertEquals(
|
|
||||||
polynomial_5,
|
|
||||||
polynomial_5 - 0,
|
|
||||||
"test 5"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(1), Rational(0), Rational(0), Rational(0)),
|
|
||||||
ListPolynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - 1,
|
|
||||||
"test 6"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(1)),
|
|
||||||
ListPolynomial(Rational(2)) - 1,
|
|
||||||
"test 7"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-2)),
|
|
||||||
ListPolynomial<Rational>() - 2,
|
|
||||||
"test 8"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_Polynomial_Int_times() {
|
|
||||||
IntModuloRing(35).listPolynomialSpace {
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(34, 2, 1, 20, 2),
|
|
||||||
ListPolynomial(22, 26, 13, 15, 26) * 27,
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(0, 0, 0, 0, 0),
|
|
||||||
ListPolynomial(7, 0, 49, 21, 14) * 15,
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
val polynomial = ListPolynomial(22, 26, 13, 15, 26)
|
|
||||||
assertSame(
|
|
||||||
zero,
|
|
||||||
polynomial * 0,
|
|
||||||
"test 3"
|
|
||||||
)
|
|
||||||
assertSame(
|
|
||||||
polynomial,
|
|
||||||
polynomial * 1,
|
|
||||||
"test 4"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_Int_Polynomial_plus() {
|
|
||||||
RationalField.listPolynomialSpace {
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)),
|
|
||||||
-3 + ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)),
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0)),
|
|
||||||
2 + ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)),
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0)),
|
|
||||||
2 + ListPolynomial(Rational(-2)),
|
|
||||||
"test 3"
|
|
||||||
)
|
|
||||||
val polynomial_4 = ListPolynomial<Rational>()
|
|
||||||
assertSame(
|
|
||||||
polynomial_4,
|
|
||||||
0 + polynomial_4,
|
|
||||||
"test 4"
|
|
||||||
)
|
|
||||||
val polynomial_5 = ListPolynomial<Rational>(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7))
|
|
||||||
assertSame(
|
|
||||||
polynomial_5,
|
|
||||||
0 + polynomial_5,
|
|
||||||
"test 5"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-1), Rational(0), Rational(0), Rational(0)),
|
|
||||||
1 + ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)),
|
|
||||||
"test 6"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-1)),
|
|
||||||
1 + ListPolynomial(Rational(-2)),
|
|
||||||
"test 7"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(2)),
|
|
||||||
2 + ListPolynomial(),
|
|
||||||
"test 8"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_Int_Polynomial_minus() {
|
|
||||||
RationalField.listPolynomialSpace {
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)),
|
|
||||||
3 - ListPolynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7)),
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0)),
|
|
||||||
-2 - ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)),
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0)),
|
|
||||||
-2 - ListPolynomial(Rational(-2)),
|
|
||||||
"test 3"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-32, 9), Rational(-8, -9), Rational(8, 7)),
|
|
||||||
0 - ListPolynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)),
|
|
||||||
"test 4"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(),
|
|
||||||
0 - ListPolynomial(),
|
|
||||||
"test 5"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(1), Rational(0), Rational(0), Rational(0)),
|
|
||||||
-1 - ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)),
|
|
||||||
"test 6"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(1)),
|
|
||||||
-1 - ListPolynomial(Rational(-2)),
|
|
||||||
"test 7"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-2)),
|
|
||||||
-2 - ListPolynomial(),
|
|
||||||
"test 8"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_Int_Polynomial_times() {
|
|
||||||
IntModuloRing(35).listPolynomialSpace {
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(34, 2, 1, 20, 2),
|
|
||||||
27 * ListPolynomial(22, 26, 13, 15, 26),
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(0, 0, 0, 0, 0),
|
|
||||||
15 * ListPolynomial(7, 0, 49, 21, 14),
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
val polynomial = ListPolynomial(22, 26, 13, 15, 26)
|
|
||||||
assertSame(
|
|
||||||
zero,
|
|
||||||
0 * polynomial,
|
|
||||||
"test 3"
|
|
||||||
)
|
|
||||||
assertSame(
|
|
||||||
polynomial,
|
|
||||||
1 * polynomial,
|
|
||||||
"test 4"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Test
|
@Test
|
||||||
fun test_Polynomial_Constant_plus() {
|
fun test_Polynomial_Constant_plus() {
|
||||||
RationalField.listPolynomialSpace {
|
RationalField.listPolynomialSpace {
|
||||||
@ -338,12 +97,12 @@ class ListPolynomialTest {
|
|||||||
IntModuloRing(35).listPolynomialSpace {
|
IntModuloRing(35).listPolynomialSpace {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
ListPolynomial(34, 2, 1, 20, 2),
|
ListPolynomial(34, 2, 1, 20, 2),
|
||||||
ListPolynomial(22, 26, 13, 15, 26) * 27.asConstant(),
|
ListPolynomial(22, 26, 13, 15, 26) * m(27),
|
||||||
"test 1"
|
"test 1"
|
||||||
)
|
)
|
||||||
assertEquals(
|
assertEquals(
|
||||||
ListPolynomial(0, 0, 0, 0, 0),
|
ListPolynomial(0, 0, 0, 0, 0),
|
||||||
ListPolynomial(7, 0, 49, 21, 14) * 15.asConstant(),
|
ListPolynomial(7, 0, 49, 21, 14) * m(15),
|
||||||
"test 2"
|
"test 2"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -433,12 +192,12 @@ class ListPolynomialTest {
|
|||||||
IntModuloRing(35).listPolynomialSpace {
|
IntModuloRing(35).listPolynomialSpace {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
ListPolynomial(34, 2, 1, 20, 2),
|
ListPolynomial(34, 2, 1, 20, 2),
|
||||||
27 * ListPolynomial(22, 26, 13, 15, 26),
|
m(27) * ListPolynomial(22, 26, 13, 15, 26),
|
||||||
"test 1"
|
"test 1"
|
||||||
)
|
)
|
||||||
assertEquals(
|
assertEquals(
|
||||||
ListPolynomial(0, 0, 0, 0, 0),
|
ListPolynomial(0, 0, 0, 0, 0),
|
||||||
15 * ListPolynomial(7, 0, 49, 21, 14),
|
m(15) * ListPolynomial(7, 0, 49, 21, 14),
|
||||||
"test 2"
|
"test 2"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,9 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.functions
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
|
||||||
import space.kscience.kmath.functions.testUtils.Rational
|
import space.kscience.kmath.functions.testUtils.Rational
|
||||||
import space.kscience.kmath.functions.testUtils.RationalField
|
import space.kscience.kmath.functions.testUtils.RationalField
|
||||||
import space.kscience.kmath.functions.testUtils.assertFailsWithTypeAndMessage
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
import kotlin.test.Ignore
|
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
@ -88,754 +86,6 @@ class ListPolynomialUtilTest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
@Test
|
@Test
|
||||||
fun test_Polynomial_substitute_Polynomial() {
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0)),
|
|
||||||
ListPolynomial(Rational(1), Rational(-2), Rational(1)).substitute(RationalField, ListPolynomial(Rational(1))),
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(709, 378), Rational(155, 252), Rational(19, 525), Rational(2, 875)),
|
|
||||||
ListPolynomial(Rational(1, 7), Rational(9, 4), Rational(1, 3), Rational(2, 7))
|
|
||||||
.substitute(RationalField, ListPolynomial(Rational(6, 9), Rational(1, 5))),
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(655, 378), Rational(155, 252), Rational(19, 525), Rational(2, 875)),
|
|
||||||
ListPolynomial(Rational(0), Rational(9, 4), Rational(1, 3), Rational(2, 7))
|
|
||||||
.substitute(RationalField, ListPolynomial(Rational(6, 9), Rational(1, 5))),
|
|
||||||
"test 3"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(677, 378), Rational(97, 180), Rational(1, 75), Rational(0)),
|
|
||||||
ListPolynomial(Rational(1, 7), Rational(9, 4), Rational(1, 3), Rational(0))
|
|
||||||
.substitute(RationalField, ListPolynomial(Rational(6, 9), Rational(1, 5))),
|
|
||||||
"test 4"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(653, 378), Rational(221, 420), Rational(4, 175), Rational(2, 875)),
|
|
||||||
ListPolynomial(Rational(1, 7), Rational(9, 4), Rational(0), Rational(2, 7))
|
|
||||||
.substitute(RationalField, ListPolynomial(Rational(6, 9), Rational(1, 5))),
|
|
||||||
"test 5"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(89, 54), Rational(0), Rational(0), Rational(0)),
|
|
||||||
ListPolynomial(Rational(0), Rational(9, 4), Rational(1, 3), Rational(0))
|
|
||||||
.substitute(RationalField, ListPolynomial(Rational(6, 9), Rational(0))),
|
|
||||||
"test 6"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
@Ignore // FIXME: This tests work only for sane realisations of the substitutions. Currently, it is not.
|
|
||||||
// Sane algorithm for substitution p(q/r) (p, q, and r are polynomials) should return denominator r^deg(p),
|
|
||||||
// not r^(deg(p)(deg(p)+1)/2) as it is now.
|
|
||||||
fun test_Polynomial_substitute_RationalFunction() {
|
|
||||||
assertEquals(
|
|
||||||
ListRationalFunction(ListPolynomial(Rational(0)), ListPolynomial(Rational(1))),
|
|
||||||
ListPolynomial(Rational(1), Rational(-2), Rational(1))
|
|
||||||
.substitute(RationalField, ListRationalFunction(ListPolynomial(Rational(1)), ListPolynomial(Rational(1)))),
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(66349, 243),
|
|
||||||
Rational(-17873, 405),
|
|
||||||
Rational(173533, 3780),
|
|
||||||
Rational(-91141, 567),
|
|
||||||
Rational(5773909, 105840),
|
|
||||||
Rational(-23243, 630),
|
|
||||||
Rational(1573, 27)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(169, 81),
|
|
||||||
Rational(-130, 27),
|
|
||||||
Rational(115, 18),
|
|
||||||
Rational(-797, 54),
|
|
||||||
Rational(1985, 144),
|
|
||||||
Rational(-55, 6),
|
|
||||||
Rational(121, 9)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(13, 3),
|
|
||||||
Rational(-9, 5),
|
|
||||||
Rational(5, 5)
|
|
||||||
).substitute(RationalField,
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(15, 1),
|
|
||||||
Rational(6, 9),
|
|
||||||
Rational(-3, 7)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(-13, 9),
|
|
||||||
Rational(10, 6),
|
|
||||||
Rational(-10, 8),
|
|
||||||
Rational(11, 3)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(-14, 9),
|
|
||||||
Rational(31, 14),
|
|
||||||
Rational(-5077, 980),
|
|
||||||
Rational(99, 35)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(25, 9),
|
|
||||||
Rational(-25, 6),
|
|
||||||
Rational(1985, 144),
|
|
||||||
Rational(-55, 6),
|
|
||||||
Rational(121, 9)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(0),
|
|
||||||
Rational(-9, 5),
|
|
||||||
Rational(5, 5)
|
|
||||||
).substitute(RationalField,
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(0),
|
|
||||||
Rational(6, 9),
|
|
||||||
Rational(-3, 7)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(0),
|
|
||||||
Rational(10, 6),
|
|
||||||
Rational(-10, 8),
|
|
||||||
Rational(11, 3)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"test 3"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(-898, 27),
|
|
||||||
Rational(271, 45),
|
|
||||||
Rational(-65, 12) ,
|
|
||||||
Rational(0),
|
|
||||||
Rational(0),
|
|
||||||
Rational(0),
|
|
||||||
Rational(0)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(-13, 9),
|
|
||||||
Rational(5, 3),
|
|
||||||
Rational(-5, 4),
|
|
||||||
Rational(0),
|
|
||||||
Rational(0),
|
|
||||||
Rational(0),
|
|
||||||
Rational(0)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(13, 3),
|
|
||||||
Rational(-9, 5),
|
|
||||||
Rational(0)
|
|
||||||
).substitute(RationalField,
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(15, 1),
|
|
||||||
Rational(6, 9),
|
|
||||||
Rational(0)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(-13, 9),
|
|
||||||
Rational(10, 6),
|
|
||||||
Rational(-10, 8),
|
|
||||||
Rational(0)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"test 4"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(56872, 243),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(-90, 7),
|
|
||||||
Rational(-3718, 81),
|
|
||||||
Rational(9, 49),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(1573, 27)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(169, 81),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(-286, 27),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(121, 9)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(13, 3),
|
|
||||||
Rational(0),
|
|
||||||
Rational(5, 5)
|
|
||||||
).substitute(RationalField,
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(15, 1),
|
|
||||||
Rational(0),
|
|
||||||
Rational(-3, 7)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(-13, 9),
|
|
||||||
Rational(0),
|
|
||||||
Rational(0),
|
|
||||||
Rational(11, 3)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"test 5"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_RationalFunction_substitute_Double() {
|
|
||||||
assertEquals(
|
|
||||||
0.0,
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(1.0, -2.0, 1.0),
|
|
||||||
ListPolynomial(-6.302012278484357, 5.831971885376948, -9.271604788393432, 5.494387848015814, -3.7187384450880785)
|
|
||||||
).substitute(1.0),
|
|
||||||
0.001,
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
2.693702616649797,
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(-5.848840571263625, -1.660411278951134, -3.793740946372443, -9.624569269490076),
|
|
||||||
ListPolynomial(-2.9680680215311073, -1.862973627119981, 4.776550592888336, -2.7320154512368466)
|
|
||||||
).substitute(-7.53452770353279),
|
|
||||||
0.001,
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
2.692226268901378,
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(0.0, -1.660411278951134, -3.793740946372443, -9.624569269490076),
|
|
||||||
ListPolynomial(0.0, -1.862973627119981, 4.776550592888336, -2.7320154512368466)
|
|
||||||
).substitute(-7.53452770353279),
|
|
||||||
0.001,
|
|
||||||
"test 3"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
-0.7394904842099175,
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(-5.848840571263625, -1.660411278951134, -3.793740946372443, 0.0),
|
|
||||||
ListPolynomial(-2.9680680215311073, -1.862973627119981, 4.776550592888336, 0.0)
|
|
||||||
).substitute(-7.53452770353279),
|
|
||||||
0.001,
|
|
||||||
"test 4"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
3.526835209398159,
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(-5.848840571263625, 0.0, 0.0, -9.624569269490076),
|
|
||||||
ListPolynomial(-2.9680680215311073, 0.0, 0.0, -2.7320154512368466)
|
|
||||||
).substitute(-7.53452770353279),
|
|
||||||
0.001,
|
|
||||||
"test 5"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_RationalFunction_substitute_Constant() {
|
|
||||||
assertEquals(
|
|
||||||
Rational(0),
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(Rational(1), Rational(-2), Rational(1)),
|
|
||||||
ListPolynomial(Rational(1)),
|
|
||||||
).substitute(RationalField, Rational(1)),
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
Rational(1149615, 61306),
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(Rational(17, 7), Rational(18, 3), Rational(18, 8), Rational(9, 1)),
|
|
||||||
ListPolynomial(Rational(11, 9), Rational(-6, 5), Rational(-12, 7), Rational(2, 1)),
|
|
||||||
).substitute(RationalField, Rational(-7, 8)),
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
Rational(3495, 586),
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(Rational(0), Rational(18, 3), Rational(18, 8), Rational(9, 1)),
|
|
||||||
ListPolynomial(Rational(0), Rational(-6, 5), Rational(-12, 7), Rational(2, 1)),
|
|
||||||
).substitute(RationalField, Rational(-7, 8)),
|
|
||||||
"test 3"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
Rational(-88605, 77392),
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(Rational(17, 7), Rational(18, 3), Rational(18, 8), Rational(0)),
|
|
||||||
ListPolynomial(Rational(11, 9), Rational(-6, 5), Rational(-12, 7), Rational(0)),
|
|
||||||
).substitute(RationalField, Rational(-7, 8)),
|
|
||||||
"test 4"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
Rational(116145, 3794),
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(Rational(17, 7), Rational(0), Rational(0), Rational(9, 1)),
|
|
||||||
ListPolynomial(Rational(11, 9), Rational(0), Rational(0), Rational(2, 1)),
|
|
||||||
).substitute(RationalField, Rational(-7, 8)),
|
|
||||||
"test 5"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_RationalFunction_substitute_Polynomial() {
|
|
||||||
assertEquals(
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(Rational(0)),
|
|
||||||
ListPolynomial(Rational(1))
|
|
||||||
),
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(Rational(1), Rational(-2), Rational(1)),
|
|
||||||
ListPolynomial(Rational(1)),
|
|
||||||
).substitute(RationalField, ListPolynomial(Rational(1))),
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(-283303, 36),
|
|
||||||
Rational(-23593, 24),
|
|
||||||
Rational(368713, 192),
|
|
||||||
Rational(1455, 8),
|
|
||||||
Rational(-272171, 1536),
|
|
||||||
Rational(-2149, 192),
|
|
||||||
Rational(469, 64),
|
|
||||||
Rational(11, 48),
|
|
||||||
Rational(-11, 96)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(5797, 12),
|
|
||||||
Rational(595, 16),
|
|
||||||
Rational(-5285, 72),
|
|
||||||
Rational(-745, 192),
|
|
||||||
Rational(1105, 288),
|
|
||||||
Rational(5, 48),
|
|
||||||
Rational(-5, 72)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(2, 9),
|
|
||||||
Rational(11, 3),
|
|
||||||
Rational(-9, 4),
|
|
||||||
Rational(-6, 1),
|
|
||||||
Rational(-11, 6)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(-2, 3),
|
|
||||||
Rational(-15, 4),
|
|
||||||
Rational(5, 9),
|
|
||||||
Rational(-5, 9)
|
|
||||||
)
|
|
||||||
).substitute(RationalField,
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(-9, 1),
|
|
||||||
Rational(-1, 4),
|
|
||||||
Rational(2, 4)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(-11, 12),
|
|
||||||
Rational(325, 192),
|
|
||||||
Rational(21, 32),
|
|
||||||
Rational(-1739, 1536),
|
|
||||||
Rational(227, 192),
|
|
||||||
Rational(-59, 64),
|
|
||||||
Rational(11, 48),
|
|
||||||
Rational(-11, 96)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(15, 16),
|
|
||||||
Rational(-265, 144),
|
|
||||||
Rational(-25, 192),
|
|
||||||
Rational(25, 288),
|
|
||||||
Rational(5, 48),
|
|
||||||
Rational(-5, 72)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(0, 9),
|
|
||||||
Rational(11, 3),
|
|
||||||
Rational(-9, 4),
|
|
||||||
Rational(-6, 1),
|
|
||||||
Rational(-11, 6)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(0, 3),
|
|
||||||
Rational(-15, 4),
|
|
||||||
Rational(5, 9),
|
|
||||||
Rational(-5, 9)
|
|
||||||
)
|
|
||||||
).substitute(RationalField,
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(-1, 4),
|
|
||||||
Rational(2, 4)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"test 3"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(149723, 36),
|
|
||||||
Rational(8483, 24),
|
|
||||||
Rational(639, 64),
|
|
||||||
Rational(3, 32),
|
|
||||||
Rational(0),
|
|
||||||
Rational(0),
|
|
||||||
Rational(0),
|
|
||||||
Rational(0),
|
|
||||||
Rational(0)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(937, 12),
|
|
||||||
Rational(55, 16),
|
|
||||||
Rational(5, 144),
|
|
||||||
Rational(0),
|
|
||||||
Rational(0),
|
|
||||||
Rational(0),
|
|
||||||
Rational(0)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(2, 9),
|
|
||||||
Rational(11, 3),
|
|
||||||
Rational(-9, 4),
|
|
||||||
Rational(-6, 1),
|
|
||||||
Rational(0)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(-2, 3),
|
|
||||||
Rational(-15, 4),
|
|
||||||
Rational(5, 9),
|
|
||||||
Rational(0)
|
|
||||||
)
|
|
||||||
).substitute(RationalField,
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(-9, 1),
|
|
||||||
Rational(-1, 4),
|
|
||||||
Rational(0)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"test 4"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(-216509, 18),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(2673, 1),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(-891, 4),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(33, 4),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(-11, 96)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(1213, 3),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(-135, 2),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(15, 4),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(-5, 72)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(2, 9),
|
|
||||||
Rational(0),
|
|
||||||
Rational(0),
|
|
||||||
Rational(0),
|
|
||||||
Rational(-11, 6)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(-2, 3),
|
|
||||||
Rational(0),
|
|
||||||
Rational(0),
|
|
||||||
Rational(-5, 9)
|
|
||||||
)
|
|
||||||
).substitute(RationalField,
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(-9, 1),
|
|
||||||
Rational(0),
|
|
||||||
Rational(2, 4)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"test 5"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
@Ignore // FIXME: This tests work only for sane realisations of the substitutions. Currently, it is not.
|
|
||||||
// Sane algorithm for substitution p(q/r) (p, q, and r are polynomials) should return denominator r^deg(p),
|
|
||||||
// not r^(deg(p)(deg(p)+1)/2) as it is now.
|
|
||||||
fun test_RationalFunction_substitute_RationalFunction() {
|
|
||||||
assertEquals(
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(Rational(0)),
|
|
||||||
ListPolynomial(Rational(1))
|
|
||||||
),
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(Rational(1), Rational(-2), Rational(1)),
|
|
||||||
ListPolynomial(Rational(1))
|
|
||||||
).substitute(RationalField,
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(Rational(1)),
|
|
||||||
ListPolynomial(Rational(1))
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(130087, 3888),
|
|
||||||
Rational(-2866333, 65610),
|
|
||||||
Rational(-5076229, 97200),
|
|
||||||
Rational(222136997, 3280500),
|
|
||||||
Rational(754719329, 20995200),
|
|
||||||
Rational(-12010283, 324000),
|
|
||||||
Rational(-2011967, 172800),
|
|
||||||
Rational(18607, 2880),
|
|
||||||
Rational(4705, 4096)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(-143820355, 3779136),
|
|
||||||
Rational(73886869, 1574640),
|
|
||||||
Rational(1440175193, 15746400),
|
|
||||||
Rational(-5308968857, 52488000),
|
|
||||||
Rational(-186910083731, 2099520000),
|
|
||||||
Rational(125043463, 1555200),
|
|
||||||
Rational(5299123, 388800),
|
|
||||||
Rational(-213757, 15360),
|
|
||||||
Rational(1380785, 147456)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(1, 1),
|
|
||||||
Rational(-10, 5),
|
|
||||||
Rational(18, 8),
|
|
||||||
Rational(-8, 8)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(-14, 8),
|
|
||||||
Rational(-14, 8),
|
|
||||||
Rational(-19, 6),
|
|
||||||
Rational(14, 3),
|
|
||||||
Rational(8, 9)
|
|
||||||
)
|
|
||||||
).substitute(RationalField,
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(14, 9),
|
|
||||||
Rational(-2, 5),
|
|
||||||
Rational(-14, 7)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(-6, 4),
|
|
||||||
Rational(5, 9),
|
|
||||||
Rational(1, 8)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(5173, 18225),
|
|
||||||
Rational(904291, 364500),
|
|
||||||
Rational(283127, 43200),
|
|
||||||
Rational(37189, 5760),
|
|
||||||
Rational(147, 128)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(-163589, 911250),
|
|
||||||
Rational(-881831, 291600),
|
|
||||||
Rational(-10722229, 777600),
|
|
||||||
Rational(-640921, 46080),
|
|
||||||
Rational(86303, 9216)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(0),
|
|
||||||
Rational(-10, 5),
|
|
||||||
Rational(18, 8),
|
|
||||||
Rational(-8, 8)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(0),
|
|
||||||
Rational(-14, 8),
|
|
||||||
Rational(-19, 6),
|
|
||||||
Rational(14, 3),
|
|
||||||
Rational(8, 9)
|
|
||||||
)
|
|
||||||
).substitute(RationalField,
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(0),
|
|
||||||
Rational(-2, 5),
|
|
||||||
Rational(-14, 7)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(0),
|
|
||||||
Rational(5, 9),
|
|
||||||
Rational(1, 8)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"test 3"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(445, 16),
|
|
||||||
Rational(-2011, 54),
|
|
||||||
Rational(1359199, 72900),
|
|
||||||
Rational(-135733, 32805),
|
|
||||||
Rational(2254, 6561),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(0, 1)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(-2018387, 46656),
|
|
||||||
Rational(82316437, 1574640),
|
|
||||||
Rational(-9335047, 393660),
|
|
||||||
Rational(15765889, 3280500),
|
|
||||||
Rational(-242089, 656100),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(0, 1)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(1, 1),
|
|
||||||
Rational(-10, 5),
|
|
||||||
Rational(18, 8),
|
|
||||||
Rational(0)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(-14, 8),
|
|
||||||
Rational(-14, 8),
|
|
||||||
Rational(-19, 6),
|
|
||||||
Rational(14, 3),
|
|
||||||
Rational(0)
|
|
||||||
)
|
|
||||||
).substitute(RationalField,
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(14, 9),
|
|
||||||
Rational(-2, 5),
|
|
||||||
Rational(0)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(-6, 4),
|
|
||||||
Rational(5, 9),
|
|
||||||
Rational(0)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"test 4"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(41635, 3888),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(-279187, 11664),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(103769, 3456),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(-11017, 768),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(4097, 4096)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(-13811791, 3779136),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(-9999395, 419904),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(6376601, 124416),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(-3668315, 82944),
|
|
||||||
Rational(0, 1),
|
|
||||||
Rational(2097089, 147456)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(1, 1),
|
|
||||||
Rational(0),
|
|
||||||
Rational(0),
|
|
||||||
Rational(-8, 8)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(-14, 8),
|
|
||||||
Rational(0),
|
|
||||||
Rational(0),
|
|
||||||
Rational(0),
|
|
||||||
Rational(8, 9)
|
|
||||||
)
|
|
||||||
).substitute(RationalField,
|
|
||||||
ListRationalFunction(
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(14, 9),
|
|
||||||
Rational(0),
|
|
||||||
Rational(-14, 7)
|
|
||||||
),
|
|
||||||
ListPolynomial(
|
|
||||||
Rational(-6, 4),
|
|
||||||
Rational(0),
|
|
||||||
Rational(1, 8)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
"test 5"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_Polynomial_derivative() {
|
fun test_Polynomial_derivative() {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
ListPolynomial(Rational(-2), Rational(2)),
|
ListPolynomial(Rational(-2), Rational(2)),
|
||||||
@ -859,55 +109,6 @@ class ListPolynomialUtilTest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
@Test
|
@Test
|
||||||
fun test_Polynomial_nthDerivative() {
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-2), Rational(2)),
|
|
||||||
ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, 1),
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertFailsWithTypeAndMessage<IllegalArgumentException>(
|
|
||||||
"Order of derivative must be non-negative",
|
|
||||||
"test2"
|
|
||||||
) {
|
|
||||||
ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, -1)
|
|
||||||
}
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(1), Rational(-2), Rational(1)),
|
|
||||||
ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, 0),
|
|
||||||
"test 3"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(2)),
|
|
||||||
ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, 2),
|
|
||||||
"test 4"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(),
|
|
||||||
ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, 3),
|
|
||||||
"test 5"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(),
|
|
||||||
ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthDerivative(RationalField, 4),
|
|
||||||
"test 6"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(8, 9), Rational(30, 7), Rational(-20, 3)),
|
|
||||||
ListPolynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).nthDerivative(RationalField, 2),
|
|
||||||
"test 7"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(8, 9), Rational(30, 7), Rational(-20, 3)),
|
|
||||||
ListPolynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).nthDerivative(RationalField, 2),
|
|
||||||
"test 8"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(8, 9), Rational(30, 7), Rational(0)),
|
|
||||||
ListPolynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).nthDerivative(RationalField, 2),
|
|
||||||
"test 9"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_Polynomial_antiderivative() {
|
fun test_Polynomial_antiderivative() {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
ListPolynomial(Rational(0), Rational(1), Rational(-1), Rational(1, 3)),
|
ListPolynomial(Rational(0), Rational(1), Rational(-1), Rational(1, 3)),
|
||||||
@ -930,53 +131,4 @@ class ListPolynomialUtilTest {
|
|||||||
"test 4"
|
"test 4"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@Test
|
|
||||||
fun test_Polynomial_nthAntiderivative() {
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0), Rational(1), Rational(-1), Rational(1, 3)),
|
|
||||||
ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, 1),
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertFailsWithTypeAndMessage<IllegalArgumentException>(
|
|
||||||
"Order of antiderivative must be non-negative",
|
|
||||||
"test2"
|
|
||||||
) {
|
|
||||||
ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, -1)
|
|
||||||
}
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(1), Rational(-2), Rational(1)),
|
|
||||||
ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, 0),
|
|
||||||
"test 3"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0), Rational(0), Rational(1, 2), Rational(-1, 3), Rational(1, 12)),
|
|
||||||
ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, 2),
|
|
||||||
"test 4"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(1, 6), Rational(-1, 12), Rational(1, 60)),
|
|
||||||
ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, 3),
|
|
||||||
"test 5"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0), Rational(1, 24), Rational(-1, 60), Rational(1, 360)),
|
|
||||||
ListPolynomial(Rational(1), Rational(-2), Rational(1)).nthAntiderivative(RationalField, 4),
|
|
||||||
"test 6"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0), Rational(0), Rational(1, 10), Rational(-4, 9), Rational(1, 27), Rational(1, 28), Rational(-1, 54)),
|
|
||||||
ListPolynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).nthAntiderivative(RationalField, 2),
|
|
||||||
"test 7"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0), Rational(1, 27), Rational(1, 28), Rational(-1, 54)),
|
|
||||||
ListPolynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).nthAntiderivative(RationalField, 2),
|
|
||||||
"test 8"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0), Rational(0), Rational(1, 10), Rational(-4, 9), Rational(1, 27), Rational(1, 28), Rational(0)),
|
|
||||||
ListPolynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).nthAntiderivative(RationalField, 2),
|
|
||||||
"test 9"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -5,15 +5,14 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.functions.testUtils
|
package space.kscience.kmath.functions.testUtils
|
||||||
|
|
||||||
import space.kscience.kmath.functions.ListPolynomial
|
import space.kscience.kmath.functions.Polynomial
|
||||||
import space.kscience.kmath.functions.ListPolynomialSpace
|
import space.kscience.kmath.functions.ListPolynomialSpace
|
||||||
import space.kscience.kmath.functions.PolynomialSpaceOverRing
|
|
||||||
|
|
||||||
|
|
||||||
public fun ListPolynomialSpace<IntModulo, IntModuloRing>.ListPolynomial(vararg coefs: Int): ListPolynomial<IntModulo> =
|
public fun ListPolynomialSpace<IntModulo, IntModuloRing>.ListPolynomial(vararg coefs: Int): Polynomial<IntModulo> =
|
||||||
ListPolynomial(coefs.map { IntModulo(it, ring.modulus) })
|
Polynomial(coefs.map { IntModulo(it, ring.modulus) })
|
||||||
public fun IntModuloRing.ListPolynomial(vararg coefs: Int): ListPolynomial<IntModulo> =
|
public fun IntModuloRing.ListPolynomial(vararg coefs: Int): Polynomial<IntModulo> =
|
||||||
ListPolynomial(coefs.map { IntModulo(it, modulus) })
|
Polynomial(coefs.map { IntModulo(it, modulus) })
|
||||||
|
|
||||||
public fun IntModuloRing.m(arg: Int): IntModulo = IntModulo(arg, modulus)
|
public fun IntModuloRing.m(arg: Int): IntModulo = IntModulo(arg, modulus)
|
||||||
public fun PolynomialSpaceOverRing<IntModulo, *, IntModuloRing>.m(arg: Int): IntModulo = IntModulo(arg, ring.modulus)
|
public fun ListPolynomialSpace<IntModulo, IntModuloRing>.m(arg: Int): IntModulo = IntModulo(arg, ring.modulus)
|
Loading…
Reference in New Issue
Block a user