Feature: Polynomials and rational functions #469
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
|
import space.kscience.kmath.operations.Ring
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a [ListPolynomial] instance with given [coefficients]. The collection of coefficients will be reversed if
|
||||||
|
* [reverse] parameter is true.
|
||||||
|
*/
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
public fun <C> ListPolynomial(coefficients: List<C>, reverse: Boolean = false): ListPolynomial<C> =
|
||||||
|
ListPolynomial(with(coefficients) { if (reverse) reversed() else this })
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a [ListPolynomial] instance with given [coefficients]. The collection of coefficients will be reversed if
|
||||||
|
* [reverse] parameter is true.
|
||||||
|
*/
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
public fun <C> ListPolynomial(vararg coefficients: C, reverse: Boolean = false): ListPolynomial<C> =
|
||||||
|
ListPolynomial(with(coefficients) { if (reverse) reversed() else toList() })
|
||||||
|
|
||||||
|
public fun <C> C.asListPolynomial() : ListPolynomial<C> = ListPolynomial(listOf(this))
|
||||||
|
|
||||||
|
|
||||||
|
// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available
|
||||||
|
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
public fun <C> ListRationalFunction(numeratorCoefficients: List<C>, denominatorCoefficients: List<C>, reverse: Boolean = false): ListRationalFunction<C> =
|
||||||
|
ListRationalFunction<C>(
|
||||||
|
ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ),
|
||||||
|
ListPolynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } )
|
||||||
|
)
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
public fun <C, A: Ring<C>> ListRationalFunctionSpace<C, A>.ListRationalFunction(numerator: ListPolynomial<C>): ListRationalFunction<C> =
|
||||||
|
ListRationalFunction<C>(numerator, polynomialOne)
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
public fun <C, A: Ring<C>> A.ListRationalFunction(numerator: ListPolynomial<C>): ListRationalFunction<C> =
|
||||||
|
ListRationalFunction<C>(numerator, ListPolynomial(listOf(one)))
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
public fun <C, A: Ring<C>> ListRationalFunctionSpace<C, A>.ListRationalFunction(numeratorCoefficients: List<C>, reverse: Boolean = false): ListRationalFunction<C> =
|
||||||
|
ListRationalFunction<C>(
|
||||||
|
ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ),
|
||||||
|
polynomialOne
|
||||||
|
)
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
public fun <C, A: Ring<C>> A.ListRationalFunction(numeratorCoefficients: List<C>, reverse: Boolean = false): ListRationalFunction<C> =
|
||||||
|
ListRationalFunction<C>(
|
||||||
|
ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ),
|
||||||
|
ListPolynomial(listOf(one))
|
||||||
|
)
|
||||||
|
|
||||||
|
//context(A)
|
||||||
|
//public fun <C, A: Ring<C>> C.asListRationalFunction() : ListRationalFunction<C> = ListRationalFunction(asListPolynomial())
|
||||||
|
//context(ListRationalFunctionSpace<C, A>)
|
||||||
|
//public fun <C, A: Ring<C>> C.asListRationalFunction() : ListRationalFunction<C> = ListRationalFunction(asListPolynomial())
|
@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
* 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.test.misc
|
||||||
|
|
||||||
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
|
import space.kscience.kmath.operations.Field
|
||||||
|
import space.kscience.kmath.operations.NumbersAddOps
|
||||||
|
|
||||||
|
class Rational {
|
||||||
|
companion object {
|
||||||
|
val ZERO: Rational = Rational(0L)
|
||||||
|
val ONE: Rational = Rational(1L)
|
||||||
|
}
|
||||||
|
|
||||||
|
val numerator: Long
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(numerator: Int, denominator: Int) : this(numerator.toLong(), denominator.toLong(), true)
|
||||||
|
constructor(numerator: Int, denominator: Long) : this(numerator.toLong(), denominator, true)
|
||||||
|
constructor(numerator: Long, denominator: Int) : this(numerator, denominator.toLong(), true)
|
||||||
|
constructor(numerator: Long, denominator: Long) : this(numerator, denominator, true)
|
||||||
|
constructor(numerator: Int) : this(numerator.toLong(), 1L, false)
|
||||||
|
constructor(numerator: Long) : this(numerator, 1L, false)
|
||||||
|
|
||||||
|
operator fun unaryPlus(): Rational = this
|
||||||
|
operator fun unaryMinus(): Rational = Rational(-this.numerator, this.denominator)
|
||||||
|
operator fun plus(other: Rational): Rational =
|
||||||
|
Rational(
|
||||||
|
numerator * other.denominator + denominator * other.numerator,
|
||||||
|
denominator * other.denominator
|
||||||
|
)
|
||||||
|
operator fun plus(other: Int): Rational =
|
||||||
|
Rational(
|
||||||
|
numerator + denominator * other.toLong(),
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
operator fun plus(other: Long): Rational =
|
||||||
|
Rational(
|
||||||
|
numerator + denominator * other,
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
operator fun minus(other: Rational): Rational =
|
||||||
|
Rational(
|
||||||
|
numerator * other.denominator - denominator * other.numerator,
|
||||||
|
denominator * other.denominator
|
||||||
|
)
|
||||||
|
operator fun minus(other: Int): Rational =
|
||||||
|
Rational(
|
||||||
|
numerator - denominator * other.toLong(),
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
operator fun minus(other: Long): Rational =
|
||||||
|
Rational(
|
||||||
|
numerator - denominator * other,
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
operator fun times(other: Rational): Rational =
|
||||||
|
Rational(
|
||||||
|
numerator * other.numerator,
|
||||||
|
denominator * other.denominator
|
||||||
|
)
|
||||||
|
operator fun times(other: Int): Rational =
|
||||||
|
Rational(
|
||||||
|
numerator * other.toLong(),
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
operator fun times(other: Long): Rational =
|
||||||
|
Rational(
|
||||||
|
numerator * other,
|
||||||
|
denominator
|
||||||
|
)
|
||||||
|
operator fun div(other: Rational): Rational =
|
||||||
|
Rational(
|
||||||
|
numerator * other.denominator,
|
||||||
|
denominator * other.numerator
|
||||||
|
)
|
||||||
|
operator fun div(other: Int): Rational =
|
||||||
|
Rational(
|
||||||
|
numerator,
|
||||||
|
denominator * other.toLong()
|
||||||
|
)
|
||||||
|
operator fun div(other: Long): Rational =
|
||||||
|
Rational(
|
||||||
|
numerator,
|
||||||
|
denominator * other
|
||||||
|
)
|
||||||
|
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", "NOTHING_TO_INLINE")
|
||||||
|
@OptIn(UnstableKMathAPI::class)
|
||||||
|
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
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user