Feature: Polynomials and rational functions #469
@ -59,7 +59,7 @@ public value class Polynomial<C>(
|
|||||||
* @param A type of provided underlying ring of constants. It's [Ring] of [C].
|
* @param A type of provided underlying ring of constants. It's [Ring] of [C].
|
||||||
* @param ring underlying ring of constants of type [A].
|
* @param ring underlying ring of constants of type [A].
|
||||||
*/
|
*/
|
||||||
public open class ListPolynomialSpace<C, A : Ring<C>>(
|
public open class PolynomialSpace<C, A : Ring<C>>(
|
||||||
/**
|
/**
|
||||||
* Underlying ring of constants. Its operations on constants are inherited by local operations on constants.
|
* Underlying ring of constants. Its operations on constants are inherited by local operations on constants.
|
||||||
*/
|
*/
|
||||||
@ -293,9 +293,9 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
|
|||||||
* @param A type of underlying ring of constants. It's [Ring] of [C].
|
* @param A type of underlying ring of constants. It's [Ring] of [C].
|
||||||
* @param ring underlying ring of constants of type [A].
|
* @param ring underlying ring of constants of type [A].
|
||||||
*/
|
*/
|
||||||
public class ScalableListPolynomialSpace<C, A>(
|
public class ScalablePolynomialSpace<C, A>(
|
||||||
ring: A,
|
ring: A,
|
||||||
) : ListPolynomialSpace<C, A>(ring), ScaleOperations<Polynomial<C>> where A : Ring<C>, A : ScaleOperations<C> {
|
) : PolynomialSpace<C, A>(ring), ScaleOperations<Polynomial<C>> where A : Ring<C>, A : ScaleOperations<C> {
|
||||||
override fun scale(a: Polynomial<C>, value: Double): Polynomial<C> =
|
override fun scale(a: Polynomial<C>, value: Double): Polynomial<C> =
|
||||||
ring { Polynomial(a.coefficients.map { scale(it, value) }) }
|
ring { Polynomial(a.coefficients.map { scale(it, value) }) }
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ package space.kscience.kmath.functions
|
|||||||
* if [reverse] parameter is true.
|
* if [reverse] parameter is true.
|
||||||
*/
|
*/
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
public fun <C> ListPolynomial(coefficients: List<C>, reverse: Boolean = false): Polynomial<C> =
|
public fun <C> Polynomial(coefficients: List<C>, reverse: Boolean = false): Polynomial<C> =
|
||||||
Polynomial(with(coefficients) { if (reverse) reversed() else this })
|
Polynomial(with(coefficients) { if (reverse) reversed() else this })
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -19,10 +19,10 @@ public fun <C> ListPolynomial(coefficients: List<C>, reverse: Boolean = false):
|
|||||||
* if [reverse] parameter is true.
|
* if [reverse] parameter is true.
|
||||||
*/
|
*/
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
public fun <C> ListPolynomial(vararg coefficients: C, reverse: Boolean = false): Polynomial<C> =
|
public fun <C> Polynomial(vararg coefficients: C, reverse: Boolean = false): Polynomial<C> =
|
||||||
Polynomial(with(coefficients) { if (reverse) reversed() else toList() })
|
Polynomial(with(coefficients) { if (reverse) reversed() else toList() })
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents [this] constant as a [Polynomial].
|
* Represents [this] constant as a [Polynomial].
|
||||||
*/
|
*/
|
||||||
public fun <C> C.asListPolynomial() : Polynomial<C> = Polynomial(listOf(this))
|
public fun <C> C.asPolynomial() : Polynomial<C> = Polynomial(listOf(this))
|
@ -14,31 +14,31 @@ import kotlin.math.pow
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a [ListPolynomialSpace] over a received ring.
|
* Creates a [PolynomialSpace] over a received ring.
|
||||||
*/
|
*/
|
||||||
public inline val <C, A : Ring<C>> A.listPolynomialSpace: ListPolynomialSpace<C, A>
|
public inline val <C, A : Ring<C>> A.polynomialSpace: PolynomialSpace<C, A>
|
||||||
get() = ListPolynomialSpace(this)
|
get() = PolynomialSpace(this)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a [ListPolynomialSpace]'s scope over a received ring.
|
* Creates a [PolynomialSpace]'s scope over a received ring.
|
||||||
*/ // TODO: When context will be ready move [ListPolynomialSpace] and add [A] to context receivers of [block]
|
*/ // 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 {
|
public inline fun <C, A : Ring<C>, R> A.polynomialSpace(block: PolynomialSpace<C, A>.() -> R): R {
|
||||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||||
return ListPolynomialSpace(this).block()
|
return PolynomialSpace(this).block()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a [ScalableListPolynomialSpace] over a received scalable ring.
|
* Creates a [ScalablePolynomialSpace] over a received scalable ring.
|
||||||
*/
|
*/
|
||||||
public inline val <C, A> A.scalableListPolynomialSpace: ScalableListPolynomialSpace<C, A> where A : Ring<C>, A : ScaleOperations<C>
|
public inline val <C, A> A.scalablePolynomialSpace: ScalablePolynomialSpace<C, A> where A : Ring<C>, A : ScaleOperations<C>
|
||||||
get() = ScalableListPolynomialSpace(this)
|
get() = ScalablePolynomialSpace(this)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a [ScalableListPolynomialSpace]'s scope over a received scalable ring.
|
* Creates a [ScalablePolynomialSpace]'s scope over a received scalable ring.
|
||||||
*/ // TODO: When context will be ready move [ListPolynomialSpace] and add [A] to context receivers of [block]
|
*/ // 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> {
|
public inline fun <C, A, R> A.scalablePolynomialSpace(block: ScalablePolynomialSpace<C, A>.() -> R): R where A : Ring<C>, A : ScaleOperations<C> {
|
||||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||||
return ScalableListPolynomialSpace(this).block()
|
return ScalablePolynomialSpace(this).block()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ package space.kscience.kmath.interpolation
|
|||||||
|
|
||||||
import space.kscience.kmath.data.XYColumnarData
|
import space.kscience.kmath.data.XYColumnarData
|
||||||
import space.kscience.kmath.functions.PiecewisePolynomial
|
import space.kscience.kmath.functions.PiecewisePolynomial
|
||||||
import space.kscience.kmath.functions.ListPolynomial
|
import space.kscience.kmath.functions.Polynomial
|
||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
import space.kscience.kmath.operations.Field
|
import space.kscience.kmath.operations.Field
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
@ -32,7 +32,7 @@ public class LinearInterpolator<T : Comparable<T>>(override val algebra: Field<T
|
|||||||
for (i in 0 until points.size - 1) {
|
for (i in 0 until points.size - 1) {
|
||||||
val slope = (points.y[i + 1] - points.y[i]) / (points.x[i + 1] - points.x[i])
|
val slope = (points.y[i + 1] - points.y[i]) / (points.x[i + 1] - points.x[i])
|
||||||
val const = points.y[i] - slope * points.x[i]
|
val const = points.y[i] - slope * points.x[i]
|
||||||
val polynomial = ListPolynomial(const, slope)
|
val polynomial = Polynomial(const, slope)
|
||||||
putRight(points.x[i + 1], polynomial)
|
putRight(points.x[i + 1], polynomial)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ package space.kscience.kmath.interpolation
|
|||||||
|
|
||||||
import space.kscience.kmath.data.XYColumnarData
|
import space.kscience.kmath.data.XYColumnarData
|
||||||
import space.kscience.kmath.functions.PiecewisePolynomial
|
import space.kscience.kmath.functions.PiecewisePolynomial
|
||||||
import space.kscience.kmath.functions.ListPolynomial
|
import space.kscience.kmath.functions.Polynomial
|
||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.operations.Field
|
import space.kscience.kmath.operations.Field
|
||||||
@ -61,7 +61,7 @@ public class SplineInterpolator<T : Comparable<T>>(
|
|||||||
val x02 = x0 * x0
|
val x02 = x0 * x0
|
||||||
val x03 = x02 * x0
|
val x03 = x02 * x0
|
||||||
//Shift coefficients to represent absolute polynomial instead of one with an offset
|
//Shift coefficients to represent absolute polynomial instead of one with an offset
|
||||||
val polynomial = ListPolynomial(
|
val polynomial = Polynomial(
|
||||||
a - b * x0 + c * x02 - d * x03,
|
a - b * x0 + c * x02 - d * x03,
|
||||||
b - 2 * c * x0 + 3 * d * x02,
|
b - 2 * c * x0 + 3 * d * x02,
|
||||||
c - 3 * d * x0,
|
c - 3 * d * x0,
|
||||||
|
@ -1,303 +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("LocalVariableName")
|
|
||||||
|
|
||||||
package space.kscience.kmath.functions
|
|
||||||
|
|
||||||
import space.kscience.kmath.functions.testUtils.*
|
|
||||||
import kotlin.test.*
|
|
||||||
|
|
||||||
|
|
||||||
class ListPolynomialTest {
|
|
||||||
@Test
|
|
||||||
fun test_Polynomial_Constant_plus() {
|
|
||||||
RationalField.listPolynomialSpace {
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)),
|
|
||||||
ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + Rational(-3),
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0)),
|
|
||||||
ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + Rational(2),
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0)),
|
|
||||||
ListPolynomial(Rational(-2)) + Rational(2),
|
|
||||||
"test 3"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0)),
|
|
||||||
ListPolynomial<Rational>() + Rational(0),
|
|
||||||
"test 4"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-1), Rational(0), Rational(0), Rational(0)),
|
|
||||||
ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + Rational(1),
|
|
||||||
"test 5"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-1)),
|
|
||||||
ListPolynomial(Rational(-2)) + Rational(1),
|
|
||||||
"test 6"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(2)),
|
|
||||||
ListPolynomial<Rational>() + Rational(2),
|
|
||||||
"test 7"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_Polynomial_Constant_minus() {
|
|
||||||
RationalField.listPolynomialSpace {
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)),
|
|
||||||
ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - Rational(-3),
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0)),
|
|
||||||
ListPolynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - Rational(2),
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0)),
|
|
||||||
ListPolynomial(Rational(2)) - Rational(2),
|
|
||||||
"test 3"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0)),
|
|
||||||
ListPolynomial<Rational>() - Rational(0),
|
|
||||||
"test 4"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(1), Rational(0), Rational(0), Rational(0)),
|
|
||||||
ListPolynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - Rational(1),
|
|
||||||
"test 5"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(1)),
|
|
||||||
ListPolynomial(Rational(2)) - Rational(1),
|
|
||||||
"test 6"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-2)),
|
|
||||||
ListPolynomial<Rational>() - Rational(2),
|
|
||||||
"test 7"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_Polynomial_Constant_times() {
|
|
||||||
IntModuloRing(35).listPolynomialSpace {
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(34, 2, 1, 20, 2),
|
|
||||||
ListPolynomial(22, 26, 13, 15, 26) * m(27),
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(0, 0, 0, 0, 0),
|
|
||||||
ListPolynomial(7, 0, 49, 21, 14) * m(15),
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_Constant_Polynomial_plus() {
|
|
||||||
RationalField.listPolynomialSpace {
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)),
|
|
||||||
Rational(-3) + ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)),
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0)),
|
|
||||||
Rational(2) + ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)),
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0)),
|
|
||||||
Rational(2) + ListPolynomial(Rational(-2)),
|
|
||||||
"test 3"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0)),
|
|
||||||
Rational(0) + ListPolynomial(),
|
|
||||||
"test 4"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-1), Rational(0), Rational(0), Rational(0)),
|
|
||||||
Rational(1) + ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)),
|
|
||||||
"test 5"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-1)),
|
|
||||||
Rational(1) + ListPolynomial(Rational(-2)),
|
|
||||||
"test 6"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(2)),
|
|
||||||
Rational(2) + ListPolynomial(),
|
|
||||||
"test 7"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_Constant_Polynomial_minus() {
|
|
||||||
RationalField.listPolynomialSpace {
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)),
|
|
||||||
Rational(3) - ListPolynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7)),
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(0)),
|
|
||||||
Rational(-2) - ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)),
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0)),
|
|
||||||
Rational(-2) - ListPolynomial(Rational(-2)),
|
|
||||||
"test 3"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0)),
|
|
||||||
Rational(0) - ListPolynomial(),
|
|
||||||
"test 4"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(1), Rational(0), Rational(0), Rational(0)),
|
|
||||||
Rational(-1) - ListPolynomial(Rational(-2), Rational(0), Rational(0), Rational(0)),
|
|
||||||
"test 5"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(1)),
|
|
||||||
Rational(-1) - ListPolynomial(Rational(-2)),
|
|
||||||
"test 6"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-2)),
|
|
||||||
Rational(-2) - ListPolynomial(),
|
|
||||||
"test 7"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_Constant_Polynomial_times() {
|
|
||||||
IntModuloRing(35).listPolynomialSpace {
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(34, 2, 1, 20, 2),
|
|
||||||
m(27) * ListPolynomial(22, 26, 13, 15, 26),
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(0, 0, 0, 0, 0),
|
|
||||||
m(15) * ListPolynomial(7, 0, 49, 21, 14),
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_Polynomial_unaryMinus() {
|
|
||||||
RationalField.listPolynomialSpace {
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7)),
|
|
||||||
-ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)),
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7), Rational(0), Rational(0)),
|
|
||||||
-ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7), Rational(0), Rational(0)),
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_Polynomial_Polynomial_plus() {
|
|
||||||
RationalField.listPolynomialSpace {
|
|
||||||
// (5/9 - 8/9 x - 8/7 x^2) + (-5/7 + 5/1 x + 5/8 x^2) ?= -10/63 + 37/9 x - 29/56 x^2
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-10, 63), Rational(37, 9), Rational(-29, 56)),
|
|
||||||
ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) +
|
|
||||||
ListPolynomial(Rational(-5, 7), Rational(5, 1), Rational(5, 8)),
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
// (-2/9 - 8/3 x) + (0 + 9/4 x + 2/4 x^2) ?= -2/9 - 5/12 x + 2/4 x^2
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-2, 9), Rational(-5, 12), Rational(2, 4)),
|
|
||||||
ListPolynomial(Rational(-2, 9), Rational(-8, 3)) +
|
|
||||||
ListPolynomial(Rational(0), Rational(9, 4), Rational(2, 4)),
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
// (-4/7 - 2/6 x + 0 x^2 + 0 x^3) + (-6/3 - 7/2 x + 2/3 x^2) ?= -18/7 - 23/6 x + 2/3 x^2
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-18, 7), Rational(-23, 6), Rational(2, 3), Rational(0)),
|
|
||||||
ListPolynomial(Rational(-4, 7), Rational(-2, 6), Rational(0), Rational(0)) +
|
|
||||||
ListPolynomial(Rational(-6, 3), Rational(-7, 2), Rational(2, 3)),
|
|
||||||
"test 3"
|
|
||||||
)
|
|
||||||
// (-2/4 - 6/9 x - 4/9 x^2) + (2/4 + 6/9 x + 4/9 x^2) ?= 0
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0), Rational(0), Rational(0)),
|
|
||||||
ListPolynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)) +
|
|
||||||
ListPolynomial(Rational(2, 4), Rational(6, 9), Rational(4, 9)),
|
|
||||||
"test 4"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_Polynomial_Polynomial_minus() {
|
|
||||||
RationalField.listPolynomialSpace {
|
|
||||||
// (5/9 - 8/9 x - 8/7 x^2) - (-5/7 + 5/1 x + 5/8 x^2) ?= 80/63 - 53/9 x - 99/56 x^2
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(80, 63), Rational(-53, 9), Rational(-99, 56)),
|
|
||||||
ListPolynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) -
|
|
||||||
ListPolynomial(Rational(-5, 7), Rational(5, 1), Rational(5, 8)),
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
// (-2/9 - 8/3 x) - (0 + 9/4 x + 2/4 x^2) ?= -2/9 - 59/12 x - 2/4 x^2
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-2, 9), Rational(-59, 12), Rational(-2, 4)),
|
|
||||||
ListPolynomial(Rational(-2, 9), Rational(-8, 3)) -
|
|
||||||
ListPolynomial(Rational(0), Rational(9, 4), Rational(2, 4)),
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
// (-4/7 - 2/6 x + 0 x^2 + 0 x^3) - (-6/3 - 7/2 x + 2/3 x^2) ?= 10/7 + 19/6 x - 2/3 x^2
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(10, 7), Rational(19, 6), Rational(-2, 3), Rational(0)),
|
|
||||||
ListPolynomial(Rational(-4, 7), Rational(-2, 6), Rational(0), Rational(0)) -
|
|
||||||
ListPolynomial(Rational(-6, 3), Rational(-7, 2), Rational(2, 3)),
|
|
||||||
"test 3"
|
|
||||||
)
|
|
||||||
// (-2/4 - 6/9 x - 4/9 x^2) - (-2/4 - 6/9 x - 4/9 x^2) ?= 0
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0), Rational(0), Rational(0)),
|
|
||||||
ListPolynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)) -
|
|
||||||
ListPolynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)),
|
|
||||||
"test 4"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_Polynomial_Polynomial_times() {
|
|
||||||
IntModuloRing(35).listPolynomialSpace {
|
|
||||||
// (1 + x + x^2) * (1 - x + x^2) ?= 1 + x^2 + x^4
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(1, 0, 1, 0, 1),
|
|
||||||
ListPolynomial(1, -1, 1) * ListPolynomial(1, 1, 1),
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
// Spoiler: 5 * 7 = 0
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(0, 0, 0, 0, 0),
|
|
||||||
ListPolynomial(5, -25, 10) * ListPolynomial(21, 14, -7),
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,134 +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.functions.testUtils.Rational
|
|
||||||
import space.kscience.kmath.functions.testUtils.RationalField
|
|
||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
|
|
||||||
|
|
||||||
@OptIn(UnstableKMathAPI::class)
|
|
||||||
class ListPolynomialUtilTest {
|
|
||||||
@Test
|
|
||||||
fun test_Polynomial_substitute_Double() {
|
|
||||||
assertEquals(
|
|
||||||
0.0,
|
|
||||||
ListPolynomial(1.0, -2.0, 1.0).substitute(1.0),
|
|
||||||
0.001,
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
0.0,
|
|
||||||
ListPolynomial(1.0, -2.0, 1.0).substitute(1.0),
|
|
||||||
0.001,
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
1.1931904761904761,
|
|
||||||
ListPolynomial(0.625, 2.6666666666666665, 0.5714285714285714, 1.5).substitute(0.2),
|
|
||||||
0.001,
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
0.5681904761904762,
|
|
||||||
ListPolynomial(0.0, 2.6666666666666665, 0.5714285714285714, 1.5).substitute(0.2),
|
|
||||||
0.001,
|
|
||||||
"test 3"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
1.1811904761904761,
|
|
||||||
ListPolynomial(0.625, 2.6666666666666665, 0.5714285714285714, 0.0).substitute(0.2),
|
|
||||||
0.001,
|
|
||||||
"test 4"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
1.1703333333333332,
|
|
||||||
ListPolynomial(0.625, 2.6666666666666665, 0.0, 1.5).substitute(0.2),
|
|
||||||
0.001,
|
|
||||||
"test 5"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_Polynomial_substitute_Constant() {
|
|
||||||
assertEquals(
|
|
||||||
Rational(0),
|
|
||||||
ListPolynomial(Rational(1), Rational(-2), Rational(1)).substitute(RationalField, Rational(1)),
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
Rational(25057, 21000),
|
|
||||||
ListPolynomial(Rational(5, 8), Rational(8, 3), Rational(4, 7), Rational(3, 2))
|
|
||||||
.substitute(RationalField, Rational(1, 5)),
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
Rational(2983, 5250),
|
|
||||||
ListPolynomial(Rational(0), Rational(8, 3), Rational(4, 7), Rational(3, 2))
|
|
||||||
.substitute(RationalField, Rational(1, 5)),
|
|
||||||
"test 3"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
Rational(4961, 4200),
|
|
||||||
ListPolynomial(Rational(5, 8), Rational(8, 3), Rational(4, 7), Rational(0))
|
|
||||||
.substitute(RationalField, Rational(1, 5)),
|
|
||||||
"test 4"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
Rational(3511, 3000),
|
|
||||||
ListPolynomial(Rational(5, 8), Rational(8, 3), Rational(0), Rational(3, 2))
|
|
||||||
.substitute(RationalField, Rational(1, 5)),
|
|
||||||
"test 5"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_Polynomial_derivative() {
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-2), Rational(2)),
|
|
||||||
ListPolynomial(Rational(1), Rational(-2), Rational(1)).derivative(RationalField),
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-8, 3), Rational(8, 9), Rational(15, 7), Rational(-20, 9)),
|
|
||||||
ListPolynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).derivative(RationalField),
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0), Rational(8, 9), Rational(15, 7), Rational(-20, 9)),
|
|
||||||
ListPolynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).derivative(RationalField),
|
|
||||||
"test 3"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(-8, 3), Rational(8, 9), Rational(15, 7), Rational(0)),
|
|
||||||
ListPolynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).derivative(RationalField),
|
|
||||||
"test 4"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
fun test_Polynomial_antiderivative() {
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0), Rational(1), Rational(-1), Rational(1, 3)),
|
|
||||||
ListPolynomial(Rational(1), Rational(-2), Rational(1)).antiderivative(RationalField),
|
|
||||||
"test 1"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0), Rational(1, 5), Rational(-4, 3), Rational(4, 27), Rational(5, 28), Rational(-1, 9)),
|
|
||||||
ListPolynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).antiderivative(RationalField),
|
|
||||||
"test 2"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0), Rational(0), Rational(0), Rational(4, 27), Rational(5, 28), Rational(-1, 9)),
|
|
||||||
ListPolynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).antiderivative(RationalField),
|
|
||||||
"test 3"
|
|
||||||
)
|
|
||||||
assertEquals(
|
|
||||||
ListPolynomial(Rational(0), Rational(1, 5), Rational(-4, 3), Rational(4, 27), Rational(5, 28), Rational(0)),
|
|
||||||
ListPolynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).antiderivative(RationalField),
|
|
||||||
"test 4"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,303 @@
|
|||||||
|
/*
|
||||||
|
* 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("LocalVariableName")
|
||||||
|
|
||||||
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
|
import space.kscience.kmath.functions.testUtils.*
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
|
||||||
|
class PolynomialTest {
|
||||||
|
@Test
|
||||||
|
fun test_Polynomial_Constant_plus() {
|
||||||
|
RationalField.polynomialSpace {
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)),
|
||||||
|
Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + Rational(-3),
|
||||||
|
"test 1"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)),
|
||||||
|
Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + Rational(2),
|
||||||
|
"test 2"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(0)),
|
||||||
|
Polynomial(Rational(-2)) + Rational(2),
|
||||||
|
"test 3"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(0)),
|
||||||
|
Polynomial<Rational>() + Rational(0),
|
||||||
|
"test 4"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(-1), Rational(0), Rational(0), Rational(0)),
|
||||||
|
Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + Rational(1),
|
||||||
|
"test 5"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(-1)),
|
||||||
|
Polynomial(Rational(-2)) + Rational(1),
|
||||||
|
"test 6"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(2)),
|
||||||
|
Polynomial<Rational>() + Rational(2),
|
||||||
|
"test 7"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
fun test_Polynomial_Constant_minus() {
|
||||||
|
RationalField.polynomialSpace {
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)),
|
||||||
|
Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - Rational(-3),
|
||||||
|
"test 1"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)),
|
||||||
|
Polynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - Rational(2),
|
||||||
|
"test 2"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(0)),
|
||||||
|
Polynomial(Rational(2)) - Rational(2),
|
||||||
|
"test 3"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(0)),
|
||||||
|
Polynomial<Rational>() - Rational(0),
|
||||||
|
"test 4"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(1), Rational(0), Rational(0), Rational(0)),
|
||||||
|
Polynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - Rational(1),
|
||||||
|
"test 5"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(1)),
|
||||||
|
Polynomial(Rational(2)) - Rational(1),
|
||||||
|
"test 6"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(-2)),
|
||||||
|
Polynomial<Rational>() - Rational(2),
|
||||||
|
"test 7"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
fun test_Polynomial_Constant_times() {
|
||||||
|
IntModuloRing(35).polynomialSpace {
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(34, 2, 1, 20, 2),
|
||||||
|
Polynomial(22, 26, 13, 15, 26) * m(27),
|
||||||
|
"test 1"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(0, 0, 0, 0, 0),
|
||||||
|
Polynomial(7, 0, 49, 21, 14) * m(15),
|
||||||
|
"test 2"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
fun test_Constant_Polynomial_plus() {
|
||||||
|
RationalField.polynomialSpace {
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)),
|
||||||
|
Rational(-3) + Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)),
|
||||||
|
"test 1"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)),
|
||||||
|
Rational(2) + Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)),
|
||||||
|
"test 2"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(0)),
|
||||||
|
Rational(2) + Polynomial(Rational(-2)),
|
||||||
|
"test 3"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(0)),
|
||||||
|
Rational(0) + Polynomial(),
|
||||||
|
"test 4"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(-1), Rational(0), Rational(0), Rational(0)),
|
||||||
|
Rational(1) + Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)),
|
||||||
|
"test 5"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(-1)),
|
||||||
|
Rational(1) + Polynomial(Rational(-2)),
|
||||||
|
"test 6"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(2)),
|
||||||
|
Rational(2) + Polynomial(),
|
||||||
|
"test 7"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
fun test_Constant_Polynomial_minus() {
|
||||||
|
RationalField.polynomialSpace {
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)),
|
||||||
|
Rational(3) - Polynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7)),
|
||||||
|
"test 1"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)),
|
||||||
|
Rational(-2) - Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)),
|
||||||
|
"test 2"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(0)),
|
||||||
|
Rational(-2) - Polynomial(Rational(-2)),
|
||||||
|
"test 3"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(0)),
|
||||||
|
Rational(0) - Polynomial(),
|
||||||
|
"test 4"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(1), Rational(0), Rational(0), Rational(0)),
|
||||||
|
Rational(-1) - Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)),
|
||||||
|
"test 5"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(1)),
|
||||||
|
Rational(-1) - Polynomial(Rational(-2)),
|
||||||
|
"test 6"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(-2)),
|
||||||
|
Rational(-2) - Polynomial(),
|
||||||
|
"test 7"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
fun test_Constant_Polynomial_times() {
|
||||||
|
IntModuloRing(35).polynomialSpace {
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(34, 2, 1, 20, 2),
|
||||||
|
m(27) * Polynomial(22, 26, 13, 15, 26),
|
||||||
|
"test 1"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(0, 0, 0, 0, 0),
|
||||||
|
m(15) * Polynomial(7, 0, 49, 21, 14),
|
||||||
|
"test 2"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
fun test_Polynomial_unaryMinus() {
|
||||||
|
RationalField.polynomialSpace {
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7)),
|
||||||
|
-Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)),
|
||||||
|
"test 1"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(-5, 9), Rational(8, 9), Rational(8, 7), Rational(0), Rational(0)),
|
||||||
|
-Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7), Rational(0), Rational(0)),
|
||||||
|
"test 2"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
fun test_Polynomial_Polynomial_plus() {
|
||||||
|
RationalField.polynomialSpace {
|
||||||
|
// (5/9 - 8/9 x - 8/7 x^2) + (-5/7 + 5/1 x + 5/8 x^2) ?= -10/63 + 37/9 x - 29/56 x^2
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(-10, 63), Rational(37, 9), Rational(-29, 56)),
|
||||||
|
Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) +
|
||||||
|
Polynomial(Rational(-5, 7), Rational(5, 1), Rational(5, 8)),
|
||||||
|
"test 1"
|
||||||
|
)
|
||||||
|
// (-2/9 - 8/3 x) + (0 + 9/4 x + 2/4 x^2) ?= -2/9 - 5/12 x + 2/4 x^2
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(-2, 9), Rational(-5, 12), Rational(2, 4)),
|
||||||
|
Polynomial(Rational(-2, 9), Rational(-8, 3)) +
|
||||||
|
Polynomial(Rational(0), Rational(9, 4), Rational(2, 4)),
|
||||||
|
"test 2"
|
||||||
|
)
|
||||||
|
// (-4/7 - 2/6 x + 0 x^2 + 0 x^3) + (-6/3 - 7/2 x + 2/3 x^2) ?= -18/7 - 23/6 x + 2/3 x^2
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(-18, 7), Rational(-23, 6), Rational(2, 3), Rational(0)),
|
||||||
|
Polynomial(Rational(-4, 7), Rational(-2, 6), Rational(0), Rational(0)) +
|
||||||
|
Polynomial(Rational(-6, 3), Rational(-7, 2), Rational(2, 3)),
|
||||||
|
"test 3"
|
||||||
|
)
|
||||||
|
// (-2/4 - 6/9 x - 4/9 x^2) + (2/4 + 6/9 x + 4/9 x^2) ?= 0
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(0), Rational(0), Rational(0)),
|
||||||
|
Polynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)) +
|
||||||
|
Polynomial(Rational(2, 4), Rational(6, 9), Rational(4, 9)),
|
||||||
|
"test 4"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
fun test_Polynomial_Polynomial_minus() {
|
||||||
|
RationalField.polynomialSpace {
|
||||||
|
// (5/9 - 8/9 x - 8/7 x^2) - (-5/7 + 5/1 x + 5/8 x^2) ?= 80/63 - 53/9 x - 99/56 x^2
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(80, 63), Rational(-53, 9), Rational(-99, 56)),
|
||||||
|
Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) -
|
||||||
|
Polynomial(Rational(-5, 7), Rational(5, 1), Rational(5, 8)),
|
||||||
|
"test 1"
|
||||||
|
)
|
||||||
|
// (-2/9 - 8/3 x) - (0 + 9/4 x + 2/4 x^2) ?= -2/9 - 59/12 x - 2/4 x^2
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(-2, 9), Rational(-59, 12), Rational(-2, 4)),
|
||||||
|
Polynomial(Rational(-2, 9), Rational(-8, 3)) -
|
||||||
|
Polynomial(Rational(0), Rational(9, 4), Rational(2, 4)),
|
||||||
|
"test 2"
|
||||||
|
)
|
||||||
|
// (-4/7 - 2/6 x + 0 x^2 + 0 x^3) - (-6/3 - 7/2 x + 2/3 x^2) ?= 10/7 + 19/6 x - 2/3 x^2
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(10, 7), Rational(19, 6), Rational(-2, 3), Rational(0)),
|
||||||
|
Polynomial(Rational(-4, 7), Rational(-2, 6), Rational(0), Rational(0)) -
|
||||||
|
Polynomial(Rational(-6, 3), Rational(-7, 2), Rational(2, 3)),
|
||||||
|
"test 3"
|
||||||
|
)
|
||||||
|
// (-2/4 - 6/9 x - 4/9 x^2) - (-2/4 - 6/9 x - 4/9 x^2) ?= 0
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(0), Rational(0), Rational(0)),
|
||||||
|
Polynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)) -
|
||||||
|
Polynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)),
|
||||||
|
"test 4"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
fun test_Polynomial_Polynomial_times() {
|
||||||
|
IntModuloRing(35).polynomialSpace {
|
||||||
|
// (1 + x + x^2) * (1 - x + x^2) ?= 1 + x^2 + x^4
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(1, 0, 1, 0, 1),
|
||||||
|
Polynomial(1, -1, 1) * Polynomial(1, 1, 1),
|
||||||
|
"test 1"
|
||||||
|
)
|
||||||
|
// Spoiler: 5 * 7 = 0
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(0, 0, 0, 0, 0),
|
||||||
|
Polynomial(5, -25, 10) * Polynomial(21, 14, -7),
|
||||||
|
"test 2"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
* 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.functions.testUtils.Rational
|
||||||
|
import space.kscience.kmath.functions.testUtils.RationalField
|
||||||
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
|
||||||
|
@OptIn(UnstableKMathAPI::class)
|
||||||
|
class PolynomialUtilTest {
|
||||||
|
@Test
|
||||||
|
fun test_Polynomial_substitute_Double() {
|
||||||
|
assertEquals(
|
||||||
|
0.0,
|
||||||
|
Polynomial(1.0, -2.0, 1.0).substitute(1.0),
|
||||||
|
0.001,
|
||||||
|
"test 1"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
0.0,
|
||||||
|
Polynomial(1.0, -2.0, 1.0).substitute(1.0),
|
||||||
|
0.001,
|
||||||
|
"test 1"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
1.1931904761904761,
|
||||||
|
Polynomial(0.625, 2.6666666666666665, 0.5714285714285714, 1.5).substitute(0.2),
|
||||||
|
0.001,
|
||||||
|
"test 2"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
0.5681904761904762,
|
||||||
|
Polynomial(0.0, 2.6666666666666665, 0.5714285714285714, 1.5).substitute(0.2),
|
||||||
|
0.001,
|
||||||
|
"test 3"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
1.1811904761904761,
|
||||||
|
Polynomial(0.625, 2.6666666666666665, 0.5714285714285714, 0.0).substitute(0.2),
|
||||||
|
0.001,
|
||||||
|
"test 4"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
1.1703333333333332,
|
||||||
|
Polynomial(0.625, 2.6666666666666665, 0.0, 1.5).substitute(0.2),
|
||||||
|
0.001,
|
||||||
|
"test 5"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
fun test_Polynomial_substitute_Constant() {
|
||||||
|
assertEquals(
|
||||||
|
Rational(0),
|
||||||
|
Polynomial(Rational(1), Rational(-2), Rational(1)).substitute(RationalField, Rational(1)),
|
||||||
|
"test 1"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Rational(25057, 21000),
|
||||||
|
Polynomial(Rational(5, 8), Rational(8, 3), Rational(4, 7), Rational(3, 2))
|
||||||
|
.substitute(RationalField, Rational(1, 5)),
|
||||||
|
"test 2"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Rational(2983, 5250),
|
||||||
|
Polynomial(Rational(0), Rational(8, 3), Rational(4, 7), Rational(3, 2))
|
||||||
|
.substitute(RationalField, Rational(1, 5)),
|
||||||
|
"test 3"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Rational(4961, 4200),
|
||||||
|
Polynomial(Rational(5, 8), Rational(8, 3), Rational(4, 7), Rational(0))
|
||||||
|
.substitute(RationalField, Rational(1, 5)),
|
||||||
|
"test 4"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Rational(3511, 3000),
|
||||||
|
Polynomial(Rational(5, 8), Rational(8, 3), Rational(0), Rational(3, 2))
|
||||||
|
.substitute(RationalField, Rational(1, 5)),
|
||||||
|
"test 5"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
fun test_Polynomial_derivative() {
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(-2), Rational(2)),
|
||||||
|
Polynomial(Rational(1), Rational(-2), Rational(1)).derivative(RationalField),
|
||||||
|
"test 1"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(-8, 3), Rational(8, 9), Rational(15, 7), Rational(-20, 9)),
|
||||||
|
Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).derivative(RationalField),
|
||||||
|
"test 2"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(0), Rational(8, 9), Rational(15, 7), Rational(-20, 9)),
|
||||||
|
Polynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).derivative(RationalField),
|
||||||
|
"test 3"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(-8, 3), Rational(8, 9), Rational(15, 7), Rational(0)),
|
||||||
|
Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).derivative(RationalField),
|
||||||
|
"test 4"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
fun test_Polynomial_antiderivative() {
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(0), Rational(1), Rational(-1), Rational(1, 3)),
|
||||||
|
Polynomial(Rational(1), Rational(-2), Rational(1)).antiderivative(RationalField),
|
||||||
|
"test 1"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(0), Rational(1, 5), Rational(-4, 3), Rational(4, 27), Rational(5, 28), Rational(-1, 9)),
|
||||||
|
Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).antiderivative(RationalField),
|
||||||
|
"test 2"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(0), Rational(0), Rational(0), Rational(4, 27), Rational(5, 28), Rational(-1, 9)),
|
||||||
|
Polynomial(Rational(0), Rational(0), Rational(4, 9), Rational(5, 7), Rational(-5, 9)).antiderivative(RationalField),
|
||||||
|
"test 3"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(0), Rational(1, 5), Rational(-4, 3), Rational(4, 27), Rational(5, 28), Rational(0)),
|
||||||
|
Polynomial(Rational(1, 5), Rational(-8, 3), Rational(4, 9), Rational(5, 7), Rational(0)).antiderivative(RationalField),
|
||||||
|
"test 4"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.integration
|
package space.kscience.kmath.integration
|
||||||
|
|
||||||
import space.kscience.kmath.functions.ListPolynomial
|
import space.kscience.kmath.functions.Polynomial
|
||||||
import space.kscience.kmath.functions.integrate
|
import space.kscience.kmath.functions.integrate
|
||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
@ -19,7 +19,7 @@ class SplineIntegralTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun integratePolynomial(){
|
fun integratePolynomial(){
|
||||||
val polynomial = ListPolynomial(1.0, 2.0, 3.0)
|
val polynomial = Polynomial(1.0, 2.0, 3.0)
|
||||||
val integral = polynomial.integrate(DoubleField,1.0..2.0)
|
val integral = polynomial.integrate(DoubleField,1.0..2.0)
|
||||||
assertEquals(11.0, integral, 0.001)
|
assertEquals(11.0, integral, 0.001)
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
package space.kscience.kmath.functions
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
import space.kscience.kmath.expressions.Symbol
|
import space.kscience.kmath.expressions.Symbol
|
||||||
|
import space.kscience.kmath.functions.testUtils.assertEquals
|
||||||
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.iota
|
import space.kscience.kmath.functions.testUtils.iota
|
||||||
|
@ -6,13 +6,13 @@
|
|||||||
package space.kscience.kmath.functions.testUtils
|
package space.kscience.kmath.functions.testUtils
|
||||||
|
|
||||||
import space.kscience.kmath.functions.Polynomial
|
import space.kscience.kmath.functions.Polynomial
|
||||||
import space.kscience.kmath.functions.ListPolynomialSpace
|
import space.kscience.kmath.functions.PolynomialSpace
|
||||||
|
|
||||||
|
|
||||||
public fun ListPolynomialSpace<IntModulo, IntModuloRing>.ListPolynomial(vararg coefs: Int): Polynomial<IntModulo> =
|
public fun PolynomialSpace<IntModulo, IntModuloRing>.Polynomial(vararg coefs: Int): Polynomial<IntModulo> =
|
||||||
Polynomial(coefs.map { IntModulo(it, ring.modulus) })
|
Polynomial(coefs.map { IntModulo(it, ring.modulus) })
|
||||||
public fun IntModuloRing.ListPolynomial(vararg coefs: Int): Polynomial<IntModulo> =
|
public fun IntModuloRing.Polynomial(vararg coefs: Int): Polynomial<IntModulo> =
|
||||||
Polynomial(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 ListPolynomialSpace<IntModulo, IntModuloRing>.m(arg: Int): IntModulo = IntModulo(arg, ring.modulus)
|
public fun PolynomialSpace<IntModulo, IntModuloRing>.m(arg: Int): IntModulo = IntModulo(arg, ring.modulus)
|
@ -0,0 +1,133 @@
|
|||||||
|
/*
|
||||||
|
* 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.testUtils
|
||||||
|
|
||||||
|
import space.kscience.kmath.operations.Ring
|
||||||
|
|
||||||
|
|
||||||
|
public class IntModulo {
|
||||||
|
public val residue: Int
|
||||||
|
public val modulus: Int
|
||||||
|
|
||||||
|
@PublishedApi
|
||||||
|
internal constructor(residue: Int, modulus: Int, toCheckInput: Boolean = true) {
|
||||||
|
if (toCheckInput) {
|
||||||
|
require(modulus != 0) { "modulus can not be zero" }
|
||||||
|
this.modulus = if (modulus < 0) -modulus else modulus
|
||||||
|
this.residue = residue.mod(this.modulus)
|
||||||
|
} else {
|
||||||
|
this.residue = residue
|
||||||
|
this.modulus = modulus
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public constructor(residue: Int, modulus: Int) : this(residue, modulus, true)
|
||||||
|
|
||||||
|
public operator fun unaryPlus(): IntModulo = this
|
||||||
|
public operator fun unaryMinus(): IntModulo =
|
||||||
|
IntModulo(
|
||||||
|
if (residue == 0) 0 else modulus - residue,
|
||||||
|
modulus,
|
||||||
|
toCheckInput = false
|
||||||
|
)
|
||||||
|
public operator fun plus(other: IntModulo): IntModulo {
|
||||||
|
require(modulus == other.modulus) { "can not add two residue different modulo" }
|
||||||
|
return IntModulo(
|
||||||
|
(residue + other.residue) % modulus,
|
||||||
|
modulus,
|
||||||
|
toCheckInput = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
public operator fun plus(other: Int): IntModulo =
|
||||||
|
IntModulo(
|
||||||
|
(residue + other) % modulus,
|
||||||
|
modulus,
|
||||||
|
toCheckInput = false
|
||||||
|
)
|
||||||
|
public operator fun minus(other: IntModulo): IntModulo {
|
||||||
|
require(modulus == other.modulus) { "can not subtract two residue different modulo" }
|
||||||
|
return IntModulo(
|
||||||
|
(residue - other.residue) % modulus,
|
||||||
|
modulus,
|
||||||
|
toCheckInput = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
public operator fun minus(other: Int): IntModulo =
|
||||||
|
IntModulo(
|
||||||
|
(residue - other) % modulus,
|
||||||
|
modulus,
|
||||||
|
toCheckInput = false
|
||||||
|
)
|
||||||
|
public operator fun times(other: IntModulo): IntModulo {
|
||||||
|
require(modulus == other.modulus) { "can not multiply two residue different modulo" }
|
||||||
|
return IntModulo(
|
||||||
|
(residue * other.residue) % modulus,
|
||||||
|
modulus,
|
||||||
|
toCheckInput = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
public operator fun times(other: Int): IntModulo =
|
||||||
|
IntModulo(
|
||||||
|
(residue * other) % modulus,
|
||||||
|
modulus,
|
||||||
|
toCheckInput = false
|
||||||
|
)
|
||||||
|
public operator fun div(other: IntModulo): IntModulo {
|
||||||
|
require(modulus == other.modulus) { "can not divide two residue different modulo" }
|
||||||
|
val (reciprocalCandidate, gcdOfOtherResidueAndModulus) = bezoutIdentityWithGCD(other.residue, modulus)
|
||||||
|
require(gcdOfOtherResidueAndModulus == 1) { "can not divide to residue that has non-trivial GCD with modulo" }
|
||||||
|
return IntModulo(
|
||||||
|
(residue * reciprocalCandidate) % modulus,
|
||||||
|
modulus,
|
||||||
|
toCheckInput = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
public operator fun div(other: Int): IntModulo {
|
||||||
|
val (reciprocalCandidate, gcdOfOtherResidueAndModulus) = bezoutIdentityWithGCD(other, modulus)
|
||||||
|
require(gcdOfOtherResidueAndModulus == 1) { "can not divide to residue that has non-trivial GCD with modulo" }
|
||||||
|
return IntModulo(
|
||||||
|
(residue * reciprocalCandidate) % modulus,
|
||||||
|
modulus,
|
||||||
|
toCheckInput = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
override fun equals(other: Any?): Boolean =
|
||||||
|
when (other) {
|
||||||
|
is IntModulo -> residue == other.residue && modulus == other.modulus
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int = residue.hashCode()
|
||||||
|
|
||||||
|
override fun toString(): String = "$residue mod $modulus"
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE")
|
||||||
|
public class IntModuloRing : Ring<IntModulo> {
|
||||||
|
|
||||||
|
public val modulus: Int
|
||||||
|
|
||||||
|
public constructor(modulus: Int) {
|
||||||
|
require(modulus != 0) { "modulus can not be zero" }
|
||||||
|
this.modulus = if (modulus < 0) -modulus else modulus
|
||||||
|
}
|
||||||
|
|
||||||
|
override inline val zero: IntModulo get() = IntModulo(0, modulus, toCheckInput = false)
|
||||||
|
override inline val one: IntModulo get() = IntModulo(1, modulus, toCheckInput = false)
|
||||||
|
|
||||||
|
public fun number(arg: Int): IntModulo = IntModulo(arg, modulus, toCheckInput = false)
|
||||||
|
|
||||||
|
override inline fun add(left: IntModulo, right: IntModulo): IntModulo = left + right
|
||||||
|
override inline fun multiply(left: IntModulo, right: IntModulo): IntModulo = left * right
|
||||||
|
|
||||||
|
override inline fun IntModulo.unaryMinus(): IntModulo = -this
|
||||||
|
override inline fun IntModulo.plus(arg: IntModulo): IntModulo = this + arg
|
||||||
|
override inline fun IntModulo.minus(arg: IntModulo): IntModulo = this - arg
|
||||||
|
override inline fun IntModulo.times(arg: IntModulo): IntModulo = this * arg
|
||||||
|
public inline fun IntModulo.div(arg: IntModulo): IntModulo = this / arg
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* 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.testUtils
|
||||||
|
|
||||||
|
import space.kscience.kmath.functions.ListPolynomial
|
||||||
|
import space.kscience.kmath.functions.Polynomial
|
||||||
|
import space.kscience.kmath.functions.ListPolynomialSpace
|
||||||
|
import space.kscience.kmath.functions.PolynomialSpaceOverRing
|
||||||
|
|
||||||
|
|
||||||
|
public fun ListPolynomialSpace<IntModulo, IntModuloRing>.ListPolynomial(vararg coefs: Int): ListPolynomial<IntModulo> =
|
||||||
|
ListPolynomial(coefs.map { IntModulo(it, ring.modulus) })
|
||||||
|
public fun IntModuloRing.ListPolynomial(vararg coefs: Int): ListPolynomial<IntModulo> =
|
||||||
|
ListPolynomial(coefs.map { IntModulo(it, modulus) })
|
||||||
|
|
||||||
|
public fun IntModuloRing.m(arg: Int): IntModulo = IntModulo(arg, modulus)
|
||||||
|
public fun PolynomialSpaceOverRing<IntModulo, *, IntModuloRing>.m(arg: Int): IntModulo = IntModulo(arg, ring.modulus)
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* 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.testUtils
|
||||||
|
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
|
|
||||||
|
internal data class BezoutIdentityWithGCD<T>(val first: T, val second: T, val gcd: T)
|
||||||
|
|
||||||
|
internal tailrec fun gcd(a: Long, b: Long): Long = if (a == 0L) abs(b) else gcd(b % a, a)
|
||||||
|
|
||||||
|
internal fun bezoutIdentityWithGCD(a: Int, b: Int): BezoutIdentityWithGCD<Int> =
|
||||||
|
when {
|
||||||
|
a < 0 && b < 0 -> with(bezoutIdentityWithGCDInternalLogic(-a, -b, 1, 0, 0, 1)) { BezoutIdentityWithGCD(-first, -second, gcd) }
|
||||||
|
a < 0 -> with(bezoutIdentityWithGCDInternalLogic(-a, b, 1, 0, 0, 1)) { BezoutIdentityWithGCD(-first, second, gcd) }
|
||||||
|
b < 0 -> with(bezoutIdentityWithGCDInternalLogic(a, -b, 1, 0, 0, 1)) { BezoutIdentityWithGCD(first, -second, gcd) }
|
||||||
|
else -> bezoutIdentityWithGCDInternalLogic(a, b, 1, 0, 0, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal tailrec fun bezoutIdentityWithGCDInternalLogic(a: Int, b: Int, m1: Int, m2: Int, m3: Int, m4: Int): BezoutIdentityWithGCD<Int> =
|
||||||
|
if (b == 0) BezoutIdentityWithGCD(m1, m3, a)
|
||||||
|
else {
|
||||||
|
val quotient = a / b
|
||||||
|
val reminder = a % b
|
||||||
|
bezoutIdentityWithGCDInternalLogic(b, reminder, m2, m1 - quotient * m2, m4, m3 - quotient * m4)
|
||||||
|
}
|
@ -0,0 +1,177 @@
|
|||||||
|
/*
|
||||||
|
* 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.testUtils
|
||||||
|
|
||||||
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
|
import space.kscience.kmath.operations.Field
|
||||||
|
import space.kscience.kmath.operations.NumbersAddOps
|
||||||
|
|
||||||
|
@Suppress("NAME_SHADOWING")
|
||||||
|
public class Rational {
|
||||||
|
public companion object {
|
||||||
|
public val ZERO: Rational = Rational(0L)
|
||||||
|
public val ONE: Rational = Rational(1L)
|
||||||
|
}
|
||||||
|
|
||||||
|
public val numerator: Long
|
||||||
|
public val denominator: Long
|
||||||
|
|
||||||
|
internal constructor(numerator: Long, denominator: Long, toCheckInput: Boolean = true) {
|
||||||
|
if (toCheckInput) {
|
||||||
|
if (denominator == 0L) throw ArithmeticException("/ by zero")
|
||||||
|
|
||||||
|
val greatestCommonDivider = gcd(numerator, denominator).let { if (denominator < 0L) -it else it }
|
||||||
|
|
||||||
|
this.numerator = numerator / greatestCommonDivider
|
||||||
|
this.denominator = denominator / greatestCommonDivider
|
||||||
|
} else {
|
||||||
|
this.numerator = numerator
|
||||||
|
this.denominator = denominator
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public constructor(numerator: Int, denominator: Int) : this(numerator.toLong(), denominator.toLong(), true)
|
||||||
|
public constructor(numerator: Int, denominator: Long) : this(numerator.toLong(), denominator, true)
|
||||||
|
public constructor(numerator: Long, denominator: Int) : this(numerator, denominator.toLong(), true)
|
||||||
|
public constructor(numerator: Long, denominator: Long) : this(numerator, denominator, true)
|
||||||
|
public constructor(numerator: Int) : this(numerator.toLong(), 1L, false)
|
||||||
|
public constructor(numerator: Long) : this(numerator, 1L, false)
|
||||||
|
|
||||||
|
public operator fun unaryPlus(): Rational = this
|
||||||
|
public operator fun unaryMinus(): Rational = Rational(-this.numerator, this.denominator)
|
||||||
|
public operator fun plus(other: Rational): Rational {
|
||||||
|
val denominatorsGcd = gcd(denominator, other.denominator)
|
||||||
|
val dividedThisDenominator = denominator / denominatorsGcd
|
||||||
|
val dividedOtherDenominator = other.denominator / denominatorsGcd
|
||||||
|
val numeratorCandidate = numerator * dividedOtherDenominator + dividedThisDenominator * other.numerator
|
||||||
|
val secondGcd = gcd(numeratorCandidate, denominatorsGcd)
|
||||||
|
return Rational(
|
||||||
|
numeratorCandidate / secondGcd,
|
||||||
|
dividedThisDenominator * (other.denominator / secondGcd),
|
||||||
|
toCheckInput = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
public operator fun plus(other: Int): Rational =
|
||||||
|
Rational(
|
||||||
|
numerator + denominator * other.toLong(),
|
||||||
|
denominator,
|
||||||
|
toCheckInput = false
|
||||||
|
)
|
||||||
|
public operator fun plus(other: Long): Rational =
|
||||||
|
Rational(
|
||||||
|
numerator + denominator * other,
|
||||||
|
denominator,
|
||||||
|
toCheckInput = false
|
||||||
|
)
|
||||||
|
public operator fun minus(other: Rational): Rational {
|
||||||
|
val denominatorsGcd = gcd(denominator, other.denominator)
|
||||||
|
val dividedThisDenominator = denominator / denominatorsGcd
|
||||||
|
val dividedOtherDenominator = other.denominator / denominatorsGcd
|
||||||
|
val numeratorCandidate = numerator * dividedOtherDenominator - dividedThisDenominator * other.numerator
|
||||||
|
val secondGcd = gcd(numeratorCandidate, denominatorsGcd)
|
||||||
|
return Rational(
|
||||||
|
numeratorCandidate / secondGcd,
|
||||||
|
dividedThisDenominator * (other.denominator / secondGcd),
|
||||||
|
toCheckInput = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
public operator fun minus(other: Int): Rational =
|
||||||
|
Rational(
|
||||||
|
numerator - denominator * other.toLong(),
|
||||||
|
denominator,
|
||||||
|
toCheckInput = false
|
||||||
|
)
|
||||||
|
public operator fun minus(other: Long): Rational =
|
||||||
|
Rational(
|
||||||
|
numerator - denominator * other,
|
||||||
|
denominator,
|
||||||
|
toCheckInput = false
|
||||||
|
)
|
||||||
|
public operator fun times(other: Rational): Rational {
|
||||||
|
val thisDenominatorAndOtherNumeratorGcd = gcd(denominator, other.numerator)
|
||||||
|
val otherDenominatorAndThisNumeratorGcd = gcd(other.denominator, numerator)
|
||||||
|
return Rational(
|
||||||
|
(numerator / otherDenominatorAndThisNumeratorGcd) * (other.numerator / thisDenominatorAndOtherNumeratorGcd),
|
||||||
|
(denominator / thisDenominatorAndOtherNumeratorGcd) * (other.denominator / otherDenominatorAndThisNumeratorGcd),
|
||||||
|
toCheckInput = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
public operator fun times(other: Int): Rational {
|
||||||
|
val other = other.toLong()
|
||||||
|
val denominatorAndOtherGcd = gcd(denominator, other)
|
||||||
|
return Rational(
|
||||||
|
numerator * (other / denominatorAndOtherGcd),
|
||||||
|
denominator / denominatorAndOtherGcd,
|
||||||
|
toCheckInput = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
public operator fun times(other: Long): Rational {
|
||||||
|
val denominatorAndOtherGcd = gcd(denominator, other)
|
||||||
|
return Rational(
|
||||||
|
numerator * (other / denominatorAndOtherGcd),
|
||||||
|
denominator / denominatorAndOtherGcd,
|
||||||
|
toCheckInput = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
public operator fun div(other: Rational): Rational {
|
||||||
|
val denominatorsGcd = gcd(denominator, other.denominator)
|
||||||
|
val numeratorsGcd = gcd(numerator, other.numerator)
|
||||||
|
return Rational(
|
||||||
|
(numerator / numeratorsGcd) * (other.denominator / denominatorsGcd),
|
||||||
|
(denominator / denominatorsGcd) * (other.numerator / numeratorsGcd)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
public operator fun div(other: Int): Rational {
|
||||||
|
val other = other.toLong()
|
||||||
|
val numeratorAndOtherGcd = gcd(numerator, other)
|
||||||
|
return Rational(
|
||||||
|
numerator / numeratorAndOtherGcd,
|
||||||
|
denominator * (other / numeratorAndOtherGcd),
|
||||||
|
toCheckInput = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
public operator fun div(other: Long): Rational {
|
||||||
|
val numeratorAndOtherGcd = gcd(numerator, other)
|
||||||
|
return Rational(
|
||||||
|
numerator / numeratorAndOtherGcd,
|
||||||
|
denominator * (other / numeratorAndOtherGcd),
|
||||||
|
toCheckInput = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
override fun equals(other: Any?): Boolean =
|
||||||
|
when (other) {
|
||||||
|
is Rational -> numerator == other.numerator && denominator == other.denominator
|
||||||
|
is Int -> numerator == other && denominator == 1L
|
||||||
|
is Long -> numerator == other && denominator == 1L
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int = 31 * numerator.hashCode() + denominator.hashCode()
|
||||||
|
|
||||||
|
override fun toString(): String = if (denominator == 1L) "$numerator" else "$numerator/$denominator"
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE")
|
||||||
|
@OptIn(UnstableKMathAPI::class)
|
||||||
|
public object RationalField : Field<Rational>, NumbersAddOps<Rational> {
|
||||||
|
override inline val zero: Rational get() = Rational.ZERO
|
||||||
|
override inline val one: Rational get() = Rational.ONE
|
||||||
|
|
||||||
|
override inline fun number(value: Number): Rational = Rational(value.toLong())
|
||||||
|
|
||||||
|
override inline fun add(left: Rational, right: Rational): Rational = left + right
|
||||||
|
override inline fun multiply(left: Rational, right: Rational): Rational = left * right
|
||||||
|
override inline fun divide(left: Rational, right: Rational): Rational = left / right
|
||||||
|
override inline fun scale(a: Rational, value: Double): Rational = a * number(value)
|
||||||
|
|
||||||
|
override inline fun Rational.unaryMinus(): Rational = -this
|
||||||
|
override inline fun Rational.plus(arg: Rational): Rational = this + arg
|
||||||
|
override inline fun Rational.minus(arg: Rational): Rational = this - arg
|
||||||
|
override inline fun Rational.times(arg: Rational): Rational = this * arg
|
||||||
|
override inline fun Rational.div(arg: Rational): Rational = this / arg
|
||||||
|
}
|
@ -91,7 +91,6 @@ public fun assertEquals(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Don't understand why but the same function from test-utils-functions module can not be used
|
|
||||||
public inline fun <reified T : Throwable> assertFailsWithTypeAndMessage(
|
public inline fun <reified T : Throwable> assertFailsWithTypeAndMessage(
|
||||||
expectedMessage: String? = null,
|
expectedMessage: String? = null,
|
||||||
assertionMessage: String? = null,
|
assertionMessage: String? = null,
|
||||||
|
Loading…
Reference in New Issue
Block a user