Feature: Polynomials and rational functions #469
@ -246,7 +246,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
override operator fun C.minus(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
override operator fun C.minus(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
||||||
if (this.isZero()) -other
|
if (this.isZero()) -other
|
||||||
else with(other.coefficients) {
|
else with(other.coefficients) {
|
||||||
if (isEmpty()) NumberedPolynomial<C>(mapOf(listOf<UInt>() to this@minus))
|
if (isEmpty()) NumberedPolynomial<C>(mapOf(emptyList<UInt>() to this@minus))
|
||||||
else NumberedPolynomial<C>(
|
else NumberedPolynomial<C>(
|
||||||
toMutableMap()
|
toMutableMap()
|
||||||
.apply {
|
.apply {
|
||||||
@ -279,7 +279,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
override operator fun NumberedPolynomial<C>.plus(other: C): NumberedPolynomial<C> =
|
override operator fun NumberedPolynomial<C>.plus(other: C): NumberedPolynomial<C> =
|
||||||
if (other.isZero()) this
|
if (other.isZero()) this
|
||||||
else with(coefficients) {
|
else with(coefficients) {
|
||||||
if (isEmpty()) NumberedPolynomial<C>(mapOf(listOf<UInt>() to other))
|
if (isEmpty()) NumberedPolynomial<C>(mapOf(emptyList<UInt>() to other))
|
||||||
else NumberedPolynomial<C>(
|
else NumberedPolynomial<C>(
|
||||||
toMutableMap()
|
toMutableMap()
|
||||||
.apply {
|
.apply {
|
||||||
@ -298,7 +298,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
override operator fun NumberedPolynomial<C>.minus(other: C): NumberedPolynomial<C> =
|
override operator fun NumberedPolynomial<C>.minus(other: C): NumberedPolynomial<C> =
|
||||||
if (other.isZero()) this
|
if (other.isZero()) this
|
||||||
else with(coefficients) {
|
else with(coefficients) {
|
||||||
if (isEmpty()) NumberedPolynomial<C>(mapOf(listOf<UInt>() to other))
|
if (isEmpty()) NumberedPolynomial<C>(mapOf(emptyList<UInt>() to other))
|
||||||
else NumberedPolynomial<C>(
|
else NumberedPolynomial<C>(
|
||||||
toMutableMap()
|
toMutableMap()
|
||||||
.apply {
|
.apply {
|
||||||
@ -416,7 +416,7 @@ public open class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
override val one: NumberedPolynomial<C> =
|
override val one: NumberedPolynomial<C> =
|
||||||
NumberedPolynomial<C>(
|
NumberedPolynomial<C>(
|
||||||
mapOf(
|
mapOf(
|
||||||
listOf<UInt>() to constantOne // 1 * x_1^0 * x_2^0 * ...
|
emptyList<UInt>() to constantOne // 1 * x_1^0 * x_2^0 * ...
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -276,7 +276,7 @@ public open class PolynomialSpace<C, A : Ring<C>>(
|
|||||||
public override operator fun Polynomial<C>.minus(other: C): Polynomial<C> =
|
public override operator fun Polynomial<C>.minus(other: C): Polynomial<C> =
|
||||||
if (other.isZero()) this
|
if (other.isZero()) this
|
||||||
else with(coefficients) {
|
else with(coefficients) {
|
||||||
if (isEmpty()) Polynomial(listOf(other))
|
if (isEmpty()) Polynomial(listOf(-other))
|
||||||
else Polynomial(
|
else Polynomial(
|
||||||
toMutableList()
|
toMutableList()
|
||||||
.apply {
|
.apply {
|
||||||
|
@ -5,16 +5,173 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.functions
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
import space.kscience.kmath.operations.BigInt
|
|
||||||
import space.kscience.kmath.operations.algebra
|
import space.kscience.kmath.operations.algebra
|
||||||
import space.kscience.kmath.operations.toBigInt
|
|
||||||
import space.kscience.kmath.test.misc.Rational
|
import space.kscience.kmath.test.misc.Rational
|
||||||
import space.kscience.kmath.test.misc.RationalField
|
import space.kscience.kmath.test.misc.RationalField
|
||||||
import space.kscience.kmath.test.misc.gcd
|
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
class PolynomialTest {
|
class PolynomialTest {
|
||||||
|
@Test
|
||||||
|
fun test_Polynomial_Int_plus() {
|
||||||
|
RationalField.polynomial {
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(-22, 9), Rational(-8, 9), Rational(-8, 7)),
|
||||||
|
Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) + -3,
|
||||||
|
"test 1"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)),
|
||||||
|
Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + 2,
|
||||||
|
"test 2"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(),
|
||||||
|
Polynomial(Rational(-2)) + 2,
|
||||||
|
"test 3"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(),
|
||||||
|
Polynomial<Rational>() + 0,
|
||||||
|
"test 4"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(-1), Rational(0), Rational(0), Rational(0)),
|
||||||
|
Polynomial(Rational(-2), Rational(0), Rational(0), Rational(0)) + 1,
|
||||||
|
"test 5"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(-1)),
|
||||||
|
Polynomial(Rational(-2)) + 1,
|
||||||
|
"test 6"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(2)),
|
||||||
|
Polynomial<Rational>() + 2,
|
||||||
|
"test 7"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
fun test_Polynomial_Int_minus() {
|
||||||
|
RationalField.polynomial {
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(32, 9), Rational(-8, 9), Rational(-8, 7)),
|
||||||
|
Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) - -3,
|
||||||
|
"test 1"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(0), Rational(0), Rational(0), Rational(0)),
|
||||||
|
Polynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - 2,
|
||||||
|
"test 2"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(),
|
||||||
|
Polynomial(Rational(2)) - 2,
|
||||||
|
"test 3"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(),
|
||||||
|
Polynomial<Rational>() - 0,
|
||||||
|
"test 4"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(1), Rational(0), Rational(0), Rational(0)),
|
||||||
|
Polynomial(Rational(2), Rational(0), Rational(0), Rational(0)) - 1,
|
||||||
|
"test 5"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(1)),
|
||||||
|
Polynomial(Rational(2)) - 1,
|
||||||
|
"test 6"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(Rational(-2)),
|
||||||
|
Polynomial<Rational>() - 2,
|
||||||
|
"test 7"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
fun test_Polynomial_Constant_plus() {
|
||||||
|
RationalField.polynomial {
|
||||||
|
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(),
|
||||||
|
Polynomial(Rational(-2)) + Rational(2),
|
||||||
|
"test 3"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(),
|
||||||
|
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.polynomial {
|
||||||
|
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(),
|
||||||
|
Polynomial(Rational(2)) - Rational(2),
|
||||||
|
"test 3"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Polynomial(),
|
||||||
|
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
|
@Test
|
||||||
fun test_Polynomial_Polynomial_plus() {
|
fun test_Polynomial_Polynomial_plus() {
|
||||||
RationalField.polynomial {
|
RationalField.polynomial {
|
||||||
@ -48,35 +205,39 @@ class PolynomialTest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// @Test
|
@Test
|
||||||
// fun test_Polynomial_Polynomial_minus() {
|
fun test_Polynomial_Polynomial_minus() {
|
||||||
// RationalField.polynomial {
|
RationalField.polynomial {
|
||||||
// assertEquals(
|
// (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
|
||||||
// Polynomial(Rational(1, 2), Rational(3, 5), Rational(-2)) +
|
assertEquals(
|
||||||
// Polynomial(Rational(3), Rational(7, 8), Rational(1, 9)),
|
Polynomial(Rational(80, 63), Rational(-53, 9), Rational(-99, 56)),
|
||||||
// Polynomial(Rational(7, 2), Rational(59, 40), Rational(-17, 9)),
|
Polynomial(Rational(5, 9), Rational(-8, 9), Rational(-8, 7)) -
|
||||||
// "test 1"
|
Polynomial(Rational(-5, 7), Rational(5, 1), Rational(5, 8)),
|
||||||
// )
|
"test 1"
|
||||||
// assertEquals(
|
)
|
||||||
// Polynomial(Rational(1, 2), Rational(3, 5)) +
|
// (-2/9 - 8/3 x) - (0 + 9/4 x + 2/4 x^2) ?= -2/9 - 59/12 x - 2/4 x^2
|
||||||
// Polynomial(Rational(3), Rational(7, 8), Rational(1, 9)),
|
assertEquals(
|
||||||
// Polynomial(Rational(7, 2), Rational(59, 40), Rational(1, 9)),
|
Polynomial(Rational(-2, 9), Rational(-59, 12), Rational(-2, 4)),
|
||||||
// "test 2"
|
Polynomial(Rational(-2, 9), Rational(-8, 3)) -
|
||||||
// )
|
Polynomial(Rational(0), Rational(9, 4), Rational(2, 4)),
|
||||||
// assertEquals(
|
"test 2"
|
||||||
// Polynomial(Rational(1, 2), Rational(3, 5), Rational(0), Rational(0)) +
|
)
|
||||||
// Polynomial(Rational(3), Rational(7, 8), Rational(1, 9)),
|
// (-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
|
||||||
// Polynomial(Rational(7, 2), Rational(59, 40), Rational(1, 9)),
|
assertEquals(
|
||||||
// "test 3"
|
Polynomial(Rational(10, 7), Rational(19, 6), Rational(-2, 3)),
|
||||||
// )
|
Polynomial(Rational(-4, 7), Rational(-2, 6), Rational(0), Rational(0)) -
|
||||||
// assertEquals(
|
Polynomial(Rational(-6, 3), Rational(-7, 2), Rational(2, 3)),
|
||||||
// Polynomial(Rational(1, 2), Rational(-3, 5), Rational(7, 3)) +
|
"test 3"
|
||||||
// Polynomial(Rational(3), Rational(3, 5), Rational(-7, 3)),
|
)
|
||||||
// Polynomial(Rational(7, 2)),
|
// (-2/4 - 6/9 x - 4/9 x^2) - (-2/4 - 6/9 x - 4/9 x^2) ?= 0
|
||||||
// "test 4"
|
assertEquals(
|
||||||
// )
|
Polynomial(),
|
||||||
// }
|
Polynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)) -
|
||||||
// }
|
Polynomial(Rational(-2, 4), Rational(-6, 9), Rational(-4, 9)),
|
||||||
|
"test 4"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@Test
|
@Test
|
||||||
fun simple_polynomial_test() {
|
fun simple_polynomial_test() {
|
||||||
val polynomial : Polynomial<Double>
|
val polynomial : Polynomial<Double>
|
||||||
|
@ -6,54 +6,23 @@
|
|||||||
package space.kscience.kmath.test.misc
|
package space.kscience.kmath.test.misc
|
||||||
|
|
||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
import space.kscience.kmath.operations.BigInt
|
|
||||||
import space.kscience.kmath.operations.Field
|
import space.kscience.kmath.operations.Field
|
||||||
import space.kscience.kmath.operations.NumbersAddOps
|
import space.kscience.kmath.operations.NumbersAddOps
|
||||||
import space.kscience.kmath.operations.toBigInt
|
|
||||||
import space.kscience.kmath.operations.BigInt.Companion.ZERO as I0
|
|
||||||
import space.kscience.kmath.operations.BigInt.Companion.ONE as I1
|
|
||||||
|
|
||||||
/**
|
class Rational {
|
||||||
* The class represents rational numbers.
|
companion object {
|
||||||
*
|
val ZERO: Rational = Rational(0L)
|
||||||
* Instances contain [numerator] and [denominator] represented as [Long].
|
val ONE: Rational = Rational(1L)
|
||||||
*
|
|
||||||
* Also [numerator] and [denominator] are coprime and [denominator] is positive.
|
|
||||||
*
|
|
||||||
* @author [Gleb Minaev](https://github.com/lounres)
|
|
||||||
*/
|
|
||||||
public class Rational: Comparable<Rational> {
|
|
||||||
public companion object {
|
|
||||||
/**
|
|
||||||
* Constant containing the zero (the additive identity) of the [Rational] field.
|
|
||||||
*/
|
|
||||||
public val ZERO: Rational = Rational(I0)
|
|
||||||
/**
|
|
||||||
* Constant containing the one (the multiplicative identity) of the [Rational] field.
|
|
||||||
*/
|
|
||||||
public val ONE: Rational = Rational(I1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
val numerator: Long
|
||||||
* Numerator of the fraction. It's stored as non-negative coprime with [denominator] integer.
|
val denominator: Long
|
||||||
*/
|
|
||||||
public val numerator: BigInt
|
|
||||||
/**
|
|
||||||
* Denominator of the fraction. It's stored as non-zero coprime with [numerator] integer.
|
|
||||||
*/
|
|
||||||
public val denominator: BigInt
|
|
||||||
|
|
||||||
/**
|
internal constructor(numerator: Long, denominator: Long, toCheckInput: Boolean = true) {
|
||||||
* If [toCheckInput] is `true` before assigning values to [Rational.numerator] and [Rational.denominator] makes them coprime and makes
|
|
||||||
* denominator positive. Otherwise, just assigns the values.
|
|
||||||
*
|
|
||||||
* @throws ArithmeticException If denominator is zero.
|
|
||||||
*/
|
|
||||||
internal constructor(numerator: BigInt, denominator: BigInt, toCheckInput: Boolean = true) {
|
|
||||||
if (toCheckInput) {
|
if (toCheckInput) {
|
||||||
if (denominator == I0) throw ArithmeticException("/ by zero")
|
if (denominator == 0L) throw ArithmeticException("/ by zero")
|
||||||
|
|
||||||
val greatestCommonDivider = gcd(numerator, denominator).let { if (denominator < I0) -it else it }
|
val greatestCommonDivider = gcd(numerator, denominator).let { if (denominator < 0L) -it else it }
|
||||||
|
|
||||||
this.numerator = numerator / greatestCommonDivider
|
this.numerator = numerator / greatestCommonDivider
|
||||||
this.denominator = denominator / greatestCommonDivider
|
this.denominator = denominator / greatestCommonDivider
|
||||||
@ -63,303 +32,86 @@ public class Rational: Comparable<Rational> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
constructor(numerator: Int, denominator: Int) : this(numerator.toLong(), denominator.toLong(), true)
|
||||||
* Before assigning values to [Rational.numerator] and [Rational.denominator] makes them coprime and makes
|
constructor(numerator: Int, denominator: Long) : this(numerator.toLong(), denominator, true)
|
||||||
* denominator positive.
|
constructor(numerator: Long, denominator: Int) : this(numerator, denominator.toLong(), true)
|
||||||
*
|
constructor(numerator: Long, denominator: Long) : this(numerator, denominator, true)
|
||||||
* @throws ArithmeticException If denominator is zero.
|
constructor(numerator: Int) : this(numerator.toLong(), 1L, false)
|
||||||
*/
|
constructor(numerator: Long) : this(numerator, 1L, false)
|
||||||
public constructor(numerator: BigInt, denominator: BigInt) : this(numerator, denominator, true)
|
|
||||||
public constructor(numerator: Int, denominator: BigInt) : this(numerator.toBigInt(), denominator, true)
|
|
||||||
public constructor(numerator: Long, denominator: BigInt) : this(numerator.toBigInt(), denominator, true)
|
|
||||||
public constructor(numerator: BigInt, denominator: Int) : this(numerator, denominator.toBigInt(), true)
|
|
||||||
public constructor(numerator: BigInt, denominator: Long) : this(numerator, denominator.toBigInt(), true)
|
|
||||||
public constructor(numerator: Int, denominator: Int) : this(numerator.toBigInt(), denominator.toBigInt(), true)
|
|
||||||
public constructor(numerator: Int, denominator: Long) : this(numerator.toBigInt(), denominator.toBigInt(), true)
|
|
||||||
public constructor(numerator: Long, denominator: Int) : this(numerator.toBigInt(), denominator.toBigInt(), true)
|
|
||||||
public constructor(numerator: Long, denominator: Long) : this(numerator.toBigInt(), denominator.toBigInt(), true)
|
|
||||||
public constructor(numerator: BigInt) : this(numerator, I1, false)
|
|
||||||
public constructor(numerator: Int) : this(numerator.toBigInt(), I1, false)
|
|
||||||
public constructor(numerator: Long) : this(numerator.toBigInt(), I1, false)
|
|
||||||
|
|
||||||
/**
|
operator fun unaryPlus(): Rational = this
|
||||||
* Returns the same instant.
|
operator fun unaryMinus(): Rational = Rational(-this.numerator, this.denominator)
|
||||||
*/
|
operator fun plus(other: Rational): Rational =
|
||||||
public operator fun unaryPlus(): Rational = this
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns negation of the instant of [Rational] field.
|
|
||||||
*/
|
|
||||||
public operator fun unaryMinus(): Rational = Rational(-this.numerator, this.denominator)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns sum of the instants of [Rational] field.
|
|
||||||
*/
|
|
||||||
public operator fun plus(other: Rational): Rational =
|
|
||||||
Rational(
|
Rational(
|
||||||
numerator * other.denominator + denominator * other.numerator,
|
numerator * other.denominator + denominator * other.numerator,
|
||||||
denominator * other.denominator
|
denominator * other.denominator
|
||||||
)
|
)
|
||||||
|
operator fun plus(other: Int): Rational =
|
||||||
/**
|
Rational(
|
||||||
* Returns sum of the instants of [Rational] field. [other] is represented as [Rational].
|
numerator + denominator * other.toLong(),
|
||||||
*/
|
denominator
|
||||||
public operator fun plus(other: BigInt): Rational =
|
)
|
||||||
|
operator fun plus(other: Long): Rational =
|
||||||
Rational(
|
Rational(
|
||||||
numerator + denominator * other,
|
numerator + denominator * other,
|
||||||
denominator
|
denominator
|
||||||
)
|
)
|
||||||
|
operator fun minus(other: Rational): Rational =
|
||||||
/**
|
|
||||||
* Returns sum of the instants of [Rational] field. [other] is represented as [Rational].
|
|
||||||
*/
|
|
||||||
public operator fun plus(other: Int): Rational =
|
|
||||||
Rational(
|
|
||||||
numerator + denominator * other.toBigInt(),
|
|
||||||
denominator
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns sum of the instants of [Rational] field. [other] is represented as [Rational].
|
|
||||||
*/
|
|
||||||
public operator fun plus(other: Long): Rational =
|
|
||||||
Rational(
|
|
||||||
numerator + denominator * other.toBigInt(),
|
|
||||||
denominator
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns difference of the instants of [Rational] field.
|
|
||||||
*/
|
|
||||||
public operator fun minus(other: Rational): Rational =
|
|
||||||
Rational(
|
Rational(
|
||||||
numerator * other.denominator - denominator * other.numerator,
|
numerator * other.denominator - denominator * other.numerator,
|
||||||
denominator * other.denominator
|
denominator * other.denominator
|
||||||
)
|
)
|
||||||
|
operator fun minus(other: Int): Rational =
|
||||||
/**
|
Rational(
|
||||||
* Returns difference of the instants of [Rational] field. [other] is represented as [Rational].
|
numerator - denominator * other.toLong(),
|
||||||
*/
|
denominator
|
||||||
public operator fun minus(other: BigInt): Rational =
|
)
|
||||||
|
operator fun minus(other: Long): Rational =
|
||||||
Rational(
|
Rational(
|
||||||
numerator - denominator * other,
|
numerator - denominator * other,
|
||||||
denominator
|
denominator
|
||||||
)
|
)
|
||||||
|
operator fun times(other: Rational): Rational =
|
||||||
/**
|
|
||||||
* Returns difference of the instants of [Rational] field. [other] is represented as [Rational].
|
|
||||||
*/
|
|
||||||
public operator fun minus(other: Int): Rational =
|
|
||||||
Rational(
|
|
||||||
numerator - denominator * other.toBigInt(),
|
|
||||||
denominator
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns difference of the instants of [Rational] field. [other] is represented as [Rational].
|
|
||||||
*/
|
|
||||||
public operator fun minus(other: Long): Rational =
|
|
||||||
Rational(
|
|
||||||
numerator - denominator * other.toBigInt(),
|
|
||||||
denominator
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns product of the instants of [Rational] field.
|
|
||||||
*/
|
|
||||||
public operator fun times(other: Rational): Rational =
|
|
||||||
Rational(
|
Rational(
|
||||||
numerator * other.numerator,
|
numerator * other.numerator,
|
||||||
denominator * other.denominator
|
denominator * other.denominator
|
||||||
)
|
)
|
||||||
|
operator fun times(other: Int): Rational =
|
||||||
/**
|
Rational(
|
||||||
* Returns product of the instants of [Rational] field. [other] is represented as [Rational].
|
numerator * other.toLong(),
|
||||||
*/
|
denominator
|
||||||
public operator fun times(other: BigInt): Rational =
|
)
|
||||||
|
operator fun times(other: Long): Rational =
|
||||||
Rational(
|
Rational(
|
||||||
numerator * other,
|
numerator * other,
|
||||||
denominator
|
denominator
|
||||||
)
|
)
|
||||||
|
operator fun div(other: Rational): Rational =
|
||||||
/**
|
|
||||||
* Returns product of the instants of [Rational] field. [other] is represented as [Rational].
|
|
||||||
*/
|
|
||||||
public operator fun times(other: Int): Rational =
|
|
||||||
Rational(
|
|
||||||
numerator * other.toBigInt(),
|
|
||||||
denominator
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns product of the instants of [Rational] field. [other] is represented as [Rational].
|
|
||||||
*/
|
|
||||||
public operator fun times(other: Long): Rational =
|
|
||||||
Rational(
|
|
||||||
numerator * other.toBigInt(),
|
|
||||||
denominator
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns quotient of the instants of [Rational] field.
|
|
||||||
*
|
|
||||||
* @throws ArithmeticException if [other] is the zero of the field it can't be a divisor.
|
|
||||||
*/
|
|
||||||
public operator fun div(other: Rational): Rational =
|
|
||||||
Rational(
|
Rational(
|
||||||
numerator * other.denominator,
|
numerator * other.denominator,
|
||||||
denominator * other.numerator
|
denominator * other.numerator
|
||||||
)
|
)
|
||||||
|
operator fun div(other: Int): Rational =
|
||||||
/**
|
Rational(
|
||||||
* Returns quotient of the instants of [Rational] field. [other] is represented as [Rational].
|
numerator,
|
||||||
*
|
denominator * other.toLong()
|
||||||
* @throws ArithmeticException if [other] is the zero of the field it can't be a divisor.
|
)
|
||||||
*/
|
operator fun div(other: Long): Rational =
|
||||||
public operator fun div(other: BigInt): Rational =
|
|
||||||
Rational(
|
Rational(
|
||||||
numerator,
|
numerator,
|
||||||
denominator * other
|
denominator * other
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns quotient of the instants of [Rational] field. [other] is represented as [Rational].
|
|
||||||
*
|
|
||||||
* @throws ArithmeticException if [other] is the zero of the field it can't be a divisor.
|
|
||||||
*/
|
|
||||||
public operator fun div(other: Int): Rational =
|
|
||||||
Rational(
|
|
||||||
numerator,
|
|
||||||
denominator * other.toBigInt()
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns quotient of the instants of [Rational] field. [other] is represented as [Rational].
|
|
||||||
*
|
|
||||||
* @throws ArithmeticException if [other] is the zero of the field it can't be a divisor.
|
|
||||||
*/
|
|
||||||
public operator fun div(other: Long): Rational =
|
|
||||||
Rational(
|
|
||||||
numerator,
|
|
||||||
denominator * other.toBigInt()
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns reminder from integral division.
|
|
||||||
*
|
|
||||||
* @throws ArithmeticException if [other] is the zero of the field it can't be a divisor.
|
|
||||||
*/
|
|
||||||
public operator fun rem(other: Rational): Rational =
|
|
||||||
Rational(
|
|
||||||
(numerator * other.denominator) % (denominator * other.numerator),
|
|
||||||
denominator * other.denominator
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns reminder from integral division.
|
|
||||||
*
|
|
||||||
* @throws ArithmeticException if [other] is the zero of the field it can't be a divisor.
|
|
||||||
*/
|
|
||||||
public operator fun rem(other: BigInt): Rational =
|
|
||||||
Rational(
|
|
||||||
numerator % denominator * other,
|
|
||||||
denominator * other
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns reminder from integral division.
|
|
||||||
*
|
|
||||||
* @throws ArithmeticException if [other] is the zero of the field it can't be a divisor.
|
|
||||||
*/
|
|
||||||
public operator fun rem(other: Int): Rational =
|
|
||||||
Rational(
|
|
||||||
numerator % denominator * other.toBigInt(),
|
|
||||||
denominator * other.toBigInt()
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns reminder from integral division.
|
|
||||||
*
|
|
||||||
* @throws ArithmeticException if [other] is the zero of the field it can't be a divisor.
|
|
||||||
*/
|
|
||||||
public operator fun rem(other: Long): Rational =
|
|
||||||
Rational(
|
|
||||||
numerator % denominator * other.toBigInt(),
|
|
||||||
denominator * other.toBigInt()
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks equality of the instance to [other].
|
|
||||||
*
|
|
||||||
* [BigInt], [Int] and [Long] values are also checked as Rational ones.
|
|
||||||
*/
|
|
||||||
override fun equals(other: Any?): Boolean =
|
override fun equals(other: Any?): Boolean =
|
||||||
when (other) {
|
when (other) {
|
||||||
is Rational -> numerator == other.numerator && denominator == other.denominator
|
is Rational -> numerator == other.numerator && denominator == other.denominator
|
||||||
is BigInt -> numerator == other && denominator == I1
|
is Int -> numerator == other && denominator == 1L
|
||||||
is Int -> numerator == other && denominator == I1
|
is Long -> numerator == other && denominator == 1L
|
||||||
is Long -> numerator == other && denominator == I1
|
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
override fun hashCode(): Int = 31 * numerator.hashCode() + denominator.hashCode()
|
||||||
* Compares the instance to [other] as [Comparable.compareTo].
|
|
||||||
*
|
|
||||||
* @see Comparable.compareTo
|
|
||||||
*/
|
|
||||||
override operator fun compareTo(other: Rational): Int = (numerator * other.denominator).compareTo(other.numerator * denominator)
|
|
||||||
|
|
||||||
/**
|
override fun toString(): String = if (denominator == 1L) "$numerator" else "$numerator/$denominator"
|
||||||
* Compares the instance to [other] as [Comparable.compareTo].
|
|
||||||
*
|
|
||||||
* [Integer] values are also checked as Rational ones.
|
|
||||||
*
|
|
||||||
* @see Comparable.compareTo
|
|
||||||
*/
|
|
||||||
public operator fun compareTo(other: BigInt): Int = (numerator).compareTo(denominator * other)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compares the instance to [other] as [Comparable.compareTo].
|
|
||||||
*
|
|
||||||
* [Int] values are also checked as Rational ones.
|
|
||||||
*
|
|
||||||
* @see Comparable.compareTo
|
|
||||||
*/
|
|
||||||
public operator fun compareTo(other: Int): Int = (numerator).compareTo(denominator * other.toBigInt())
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compares the instance to [other] as [Comparable.compareTo].
|
|
||||||
*
|
|
||||||
* [Long] values are also checked as Rational ones.
|
|
||||||
*
|
|
||||||
* @see Comparable.compareTo
|
|
||||||
*/
|
|
||||||
public operator fun compareTo(other: Long): Int = (numerator).compareTo(denominator * other.toBigInt())
|
|
||||||
|
|
||||||
public override fun hashCode(): Int = 31 * numerator.hashCode() + denominator.hashCode()
|
|
||||||
|
|
||||||
// /** Creates a range from this value to the specified [other] value. */
|
|
||||||
// operator fun rangeTo(other: JBInt) = ClosedRationalRange(this, other.toRational())
|
|
||||||
// /** Creates a range from this value to the specified [other] value. */
|
|
||||||
// operator fun rangeTo(other: Rational) = ClosedRationalRange(this, other)
|
|
||||||
// /** Creates a range from this value to the specified [other] value. */
|
|
||||||
// operator fun rangeTo(other: Int) = ClosedRationalRange(this, other.toRational())
|
|
||||||
// /** Creates a range from this value to the specified [other] value. */
|
|
||||||
// operator fun rangeTo(other: Long) = ClosedRationalRange(this, other.toRational())
|
|
||||||
|
|
||||||
public fun toRational(): Rational = this
|
|
||||||
|
|
||||||
public fun toBigInt(): BigInt = numerator / denominator
|
|
||||||
|
|
||||||
// public fun toInt(): Int = (numerator / denominator).toInt()
|
|
||||||
//
|
|
||||||
// public fun toLong(): Long = (numerator / denominator).toLong()
|
|
||||||
//
|
|
||||||
// public fun toDouble(): Double = (numerator.toDouble() / denominator.toDouble())
|
|
||||||
//
|
|
||||||
// public fun toFloat(): Float = (numerator.toFloat() / denominator.toFloat())
|
|
||||||
|
|
||||||
public override fun toString(): String = if (denominator == I1) "$numerator" else "$numerator/$denominator"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -368,7 +120,7 @@ public class Rational: Comparable<Rational> {
|
|||||||
*/
|
*/
|
||||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
||||||
@OptIn(UnstableKMathAPI::class)
|
@OptIn(UnstableKMathAPI::class)
|
||||||
public object RationalField : Field<Rational>, NumbersAddOps<Rational> {
|
object RationalField : Field<Rational>, NumbersAddOps<Rational> {
|
||||||
override inline val zero: Rational get() = Rational.ZERO
|
override inline val zero: Rational get() = Rational.ZERO
|
||||||
override inline val one: Rational get() = Rational.ONE
|
override inline val one: Rational get() = Rational.ONE
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ class RationalWithMemorization private constructor(
|
|||||||
val value: Rational,
|
val value: Rational,
|
||||||
override val memory : OperationsMemory
|
override val memory : OperationsMemory
|
||||||
): WithMemorization {
|
): WithMemorization {
|
||||||
public companion object {
|
companion object {
|
||||||
/**
|
/**
|
||||||
* Constant containing the zero (the additive identity) of the [Rational] field.
|
* Constant containing the zero (the additive identity) of the [Rational] field.
|
||||||
*/
|
*/
|
||||||
@ -22,48 +22,42 @@ class RationalWithMemorization private constructor(
|
|||||||
*/
|
*/
|
||||||
public val ONE: RationalWithMemorization = RationalWithMemorization(Rational.ONE, object : Endpoint {})
|
public val ONE: RationalWithMemorization = RationalWithMemorization(Rational.ONE, object : Endpoint {})
|
||||||
}
|
}
|
||||||
public constructor(numerator: BigInt, denominator: BigInt) : this(Rational(numerator, denominator), object : Endpoint {})
|
constructor(numerator: Int, denominator: Int) : this(Rational(numerator, denominator), object : Endpoint {})
|
||||||
public constructor(numerator: Int, denominator: BigInt) : this(Rational(numerator, denominator), object : Endpoint {})
|
constructor(numerator: Int, denominator: Long) : this(Rational(numerator, denominator), object : Endpoint {})
|
||||||
public constructor(numerator: Long, denominator: BigInt) : this(Rational(numerator, denominator), object : Endpoint {})
|
constructor(numerator: Long, denominator: Int) : this(Rational(numerator, denominator), object : Endpoint {})
|
||||||
public constructor(numerator: BigInt, denominator: Int) : this(Rational(numerator, denominator), object : Endpoint {})
|
constructor(numerator: Long, denominator: Long) : this(Rational(numerator, denominator), object : Endpoint {})
|
||||||
public constructor(numerator: BigInt, denominator: Long) : this(Rational(numerator, denominator), object : Endpoint {})
|
constructor(numerator: Int) : this(Rational(numerator), object : Endpoint {})
|
||||||
public constructor(numerator: Int, denominator: Int) : this(Rational(numerator, denominator), object : Endpoint {})
|
constructor(numerator: Long) : this(Rational(numerator), object : Endpoint {})
|
||||||
public constructor(numerator: Int, denominator: Long) : this(Rational(numerator, denominator), object : Endpoint {})
|
|
||||||
public constructor(numerator: Long, denominator: Int) : this(Rational(numerator, denominator), object : Endpoint {})
|
|
||||||
public constructor(numerator: Long, denominator: Long) : this(Rational(numerator, denominator), object : Endpoint {})
|
|
||||||
public constructor(numerator: BigInt) : this(Rational(numerator), object : Endpoint {})
|
|
||||||
public constructor(numerator: Int) : this(Rational(numerator), object : Endpoint {})
|
|
||||||
public constructor(numerator: Long) : this(Rational(numerator), object : Endpoint {})
|
|
||||||
|
|
||||||
public operator fun unaryPlus(): RationalWithMemorization = this
|
operator fun unaryPlus(): RationalWithMemorization = this
|
||||||
public operator fun unaryMinus(): RationalWithMemorization = RationalWithMemorization(
|
operator fun unaryMinus(): RationalWithMemorization = RationalWithMemorization(
|
||||||
-value,
|
-value,
|
||||||
object : Negation {
|
object : Negation {
|
||||||
override val negated: OperationsMemory = memory
|
override val negated: OperationsMemory = memory
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
public operator fun plus(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization(
|
operator fun plus(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization(
|
||||||
value + other.value,
|
value + other.value,
|
||||||
object : Sum {
|
object : Sum {
|
||||||
override val augend: OperationsMemory = memory
|
override val augend: OperationsMemory = memory
|
||||||
override val addend: OperationsMemory = other.memory
|
override val addend: OperationsMemory = other.memory
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
public operator fun minus(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization(
|
operator fun minus(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization(
|
||||||
value - other.value,
|
value - other.value,
|
||||||
object : Difference {
|
object : Difference {
|
||||||
override val minuend: OperationsMemory = memory
|
override val minuend: OperationsMemory = memory
|
||||||
override val subtrahend: OperationsMemory = other.memory
|
override val subtrahend: OperationsMemory = other.memory
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
public operator fun times(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization(
|
operator fun times(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization(
|
||||||
value * other.value,
|
value * other.value,
|
||||||
object : Product {
|
object : Product {
|
||||||
override val multiplicand: OperationsMemory = memory
|
override val multiplicand: OperationsMemory = memory
|
||||||
override val multiplier: OperationsMemory = other.memory
|
override val multiplier: OperationsMemory = other.memory
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
public operator fun div(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization(
|
operator fun div(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization(
|
||||||
value / other.value,
|
value / other.value,
|
||||||
object : Quotient {
|
object : Quotient {
|
||||||
override val dividend: OperationsMemory = memory
|
override val dividend: OperationsMemory = memory
|
||||||
@ -71,16 +65,16 @@ class RationalWithMemorization private constructor(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
public override fun equals(other: Any?): Boolean =
|
override fun equals(other: Any?): Boolean =
|
||||||
other is RationalWithMemorization && value == other.value
|
other is RationalWithMemorization && value == other.value
|
||||||
|
|
||||||
public override fun hashCode(): Int = value.hashCode()
|
override fun hashCode(): Int = value.hashCode()
|
||||||
|
|
||||||
public override fun toString(): String = value.toString()
|
override fun toString(): String = value.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
||||||
public object RationalWithMemorizationRing : Ring<RationalWithMemorization> {
|
object RationalWithMemorizationRing : Ring<RationalWithMemorization> {
|
||||||
override inline val zero: RationalWithMemorization get() = RationalWithMemorization.ZERO
|
override inline val zero: RationalWithMemorization get() = RationalWithMemorization.ZERO
|
||||||
override inline val one: RationalWithMemorization get() = RationalWithMemorization.ONE
|
override inline val one: RationalWithMemorization get() = RationalWithMemorization.ONE
|
||||||
|
|
||||||
@ -94,7 +88,7 @@ public object RationalWithMemorizationRing : Ring<RationalWithMemorization> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
||||||
public object RationalWithMemorizationField : Field<RationalWithMemorization> {
|
object RationalWithMemorizationField : Field<RationalWithMemorization> {
|
||||||
override inline val zero: RationalWithMemorization get() = RationalWithMemorization.ZERO
|
override inline val zero: RationalWithMemorization get() = RationalWithMemorization.ZERO
|
||||||
override inline val one: RationalWithMemorization get() = RationalWithMemorization.ONE
|
override inline val one: RationalWithMemorization get() = RationalWithMemorization.ONE
|
||||||
|
|
||||||
|
@ -5,21 +5,8 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.test.misc
|
package space.kscience.kmath.test.misc
|
||||||
|
|
||||||
import space.kscience.kmath.operations.*
|
import kotlin.math.abs
|
||||||
import space.kscience.kmath.operations.BigInt.Companion.ZERO as I0
|
|
||||||
|
|
||||||
// TODO: Move to corresponding module "kmath-number-theory"
|
// TODO: Move to corresponding module "kmath-number-theory"
|
||||||
|
|
||||||
/**
|
tailrec fun gcd(a: Long, b: Long): Long = if (a == 0L) abs(b) else gcd(b % a, a)
|
||||||
* Computes [Greatest Common Divisor](https://en.wikipedia.org/wiki/Greatest_common_divisor) of [a] and [b].
|
|
||||||
*
|
|
||||||
* It's computed by [Euclidean algorithm](https://en.wikipedia.org/wiki/Greatest_common_divisor#Euclidean_algorithm).
|
|
||||||
* Hence, its time complexity is $$O(\log(a+b))$$ (see [Wolfram MathWorld](https://mathworld.wolfram.com/EuclideanAlgorithm.html)).
|
|
||||||
*/
|
|
||||||
public tailrec fun gcd(a: BigInt, b: BigInt): BigInt = if (a == I0) abs(b) else gcd(b % a, a)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Computes [Greatest Common Divisor](https://en.wikipedia.org/wiki/Greatest_common_divisor) of the [values].
|
|
||||||
*/
|
|
||||||
public fun gcd(vararg values: BigInt): BigInt = values.reduce(::gcd)
|
|
||||||
public fun gcd(values: Iterable<BigInt>): BigInt = values.reduce(::gcd)
|
|
Loading…
Reference in New Issue
Block a user