Feature: Polynomials and rational functions #469

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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