Feature: Polynomials and rational functions #469

Merged
lounres merged 132 commits from feature/polynomials into dev 2022-07-28 18:04:06 +03:00
5 changed files with 0 additions and 466 deletions
Showing only changes of commit a6b86eeee1 - Show all commits

View File

@ -1,142 +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.test.misc
import space.kscience.kmath.functions.ListPolynomial
import space.kscience.kmath.functions.ListPolynomialSpace
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.Ring
class IntModulo {
val residue: Int
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(modulus)
} else {
this.residue = residue
this.modulus = modulus
}
}
constructor(residue: Int, modulus: Int) : this(residue, modulus, true)
operator fun unaryPlus(): IntModulo = this
operator fun unaryMinus(): IntModulo =
IntModulo(
if (residue == 0) 0 else modulus - residue,
modulus,
toCheckInput = false
)
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
)
}
operator fun plus(other: Int): IntModulo =
IntModulo(
(residue + other) % modulus,
modulus,
toCheckInput = false
)
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
)
}
operator fun minus(other: Int): IntModulo =
IntModulo(
(residue - other) % modulus,
modulus,
toCheckInput = false
)
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
)
}
operator fun times(other: Int): IntModulo =
IntModulo(
(residue * other) % modulus,
modulus,
toCheckInput = false
)
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
)
}
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", "NOTHING_TO_INLINE")
@OptIn(UnstableKMathAPI::class)
class IntModuloRing : Ring<IntModulo> {
val modulus: Int
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)
fun number(arg: Int) = 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
inline fun IntModulo.div(arg: IntModulo): IntModulo = this / arg
}
fun ListPolynomialSpace<IntModulo, IntModuloRing>.number(arg: Int) = IntModulo(arg, ring.modulus, toCheckInput = false)
fun ListPolynomialSpace<IntModulo, IntModuloRing>.ListPolynomial(vararg coefs: Int): ListPolynomial<IntModulo> =
ListPolynomial(coefs.map { IntModulo(it, ring.modulus) })
fun IntModuloRing.ListPolynomial(vararg coefs: Int): ListPolynomial<IntModulo> =
ListPolynomial(coefs.map { IntModulo(it, modulus) })

View File

@ -1,135 +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.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
}

View File

@ -1,107 +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.test.misc
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.*
class RationalWithMemorization private constructor(
val value: Rational,
override val memory : OperationsMemory
): WithMemorization {
companion object {
/**
* Constant containing the zero (the additive identity) of the [Rational] field.
*/
public val ZERO: RationalWithMemorization = RationalWithMemorization(Rational.ZERO, object : Endpoint {})
/**
* Constant containing the one (the multiplicative identity) of the [Rational] field.
*/
public val ONE: RationalWithMemorization = RationalWithMemorization(Rational.ONE, object : Endpoint {})
}
constructor(numerator: Int, denominator: Int) : this(Rational(numerator, denominator), object : Endpoint {})
constructor(numerator: Int, denominator: Long) : this(Rational(numerator, denominator), object : Endpoint {})
constructor(numerator: Long, denominator: Int) : this(Rational(numerator, denominator), object : Endpoint {})
constructor(numerator: Long, denominator: Long) : this(Rational(numerator, denominator), object : Endpoint {})
constructor(numerator: Int) : this(Rational(numerator), object : Endpoint {})
constructor(numerator: Long) : this(Rational(numerator), object : Endpoint {})
operator fun unaryPlus(): RationalWithMemorization = this
operator fun unaryMinus(): RationalWithMemorization = RationalWithMemorization(
-value,
object : Negation {
override val negated: OperationsMemory = memory
}
)
operator fun plus(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization(
value + other.value,
object : Sum {
override val augend: OperationsMemory = memory
override val addend: OperationsMemory = other.memory
}
)
operator fun minus(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization(
value - other.value,
object : Difference {
override val minuend: OperationsMemory = memory
override val subtrahend: OperationsMemory = other.memory
}
)
operator fun times(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization(
value * other.value,
object : Product {
override val multiplicand: OperationsMemory = memory
override val multiplier: OperationsMemory = other.memory
}
)
operator fun div(other: RationalWithMemorization): RationalWithMemorization = RationalWithMemorization(
value / other.value,
object : Quotient {
override val dividend: OperationsMemory = memory
override val divisor: OperationsMemory = other.memory
}
)
override fun equals(other: Any?): Boolean =
other is RationalWithMemorization && value == other.value
override fun hashCode(): Int = value.hashCode()
override fun toString(): String = value.toString()
}
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
object RationalWithMemorizationRing : Ring<RationalWithMemorization> {
override inline val zero: RationalWithMemorization get() = RationalWithMemorization.ZERO
override inline val one: RationalWithMemorization get() = RationalWithMemorization.ONE
override inline fun add(left: RationalWithMemorization, right: RationalWithMemorization): RationalWithMemorization = left + right
override inline fun multiply(left: RationalWithMemorization, right: RationalWithMemorization): RationalWithMemorization = left * right
override inline fun RationalWithMemorization.unaryMinus(): RationalWithMemorization = -this
override inline fun RationalWithMemorization.plus(arg: RationalWithMemorization): RationalWithMemorization = this + arg
override inline fun RationalWithMemorization.minus(arg: RationalWithMemorization): RationalWithMemorization = this - arg
override inline fun RationalWithMemorization.times(arg: RationalWithMemorization): RationalWithMemorization = this * arg
}
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
object RationalWithMemorizationField : Field<RationalWithMemorization> {
override inline val zero: RationalWithMemorization get() = RationalWithMemorization.ZERO
override inline val one: RationalWithMemorization get() = RationalWithMemorization.ONE
override inline fun number(value: Number): RationalWithMemorization = RationalWithMemorization(value.toLong())
override inline fun add(left: RationalWithMemorization, right: RationalWithMemorization): RationalWithMemorization = left + right
override inline fun multiply(left: RationalWithMemorization, right: RationalWithMemorization): RationalWithMemorization = left * right
override inline fun divide(left: RationalWithMemorization, right: RationalWithMemorization): RationalWithMemorization = left / right
override inline fun scale(a: RationalWithMemorization, value: Double): RationalWithMemorization = a * number(value)
override inline fun RationalWithMemorization.unaryMinus(): RationalWithMemorization = -this
override inline fun RationalWithMemorization.plus(arg: RationalWithMemorization): RationalWithMemorization = this + arg
override inline fun RationalWithMemorization.minus(arg: RationalWithMemorization): RationalWithMemorization = this - arg
override inline fun RationalWithMemorization.times(arg: RationalWithMemorization): RationalWithMemorization = this * arg
override inline fun RationalWithMemorization.div(arg: RationalWithMemorization): RationalWithMemorization = this / arg
}

View File

@ -1,51 +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.test.misc
sealed interface OperationsMemory
interface Endpoint: OperationsMemory
interface Negation: OperationsMemory {
val negated: OperationsMemory
}
interface Sum: OperationsMemory {
val augend: OperationsMemory
val addend: OperationsMemory
}
interface Difference: OperationsMemory {
val minuend: OperationsMemory
val subtrahend: OperationsMemory
}
interface Product: OperationsMemory {
val multiplicand: OperationsMemory
val multiplier: OperationsMemory
}
interface Quotient: OperationsMemory {
val dividend: OperationsMemory
val divisor: OperationsMemory
}
fun equalMemories(one: OperationsMemory, other: OperationsMemory) : Boolean =
when(one) {
is Negation -> other is Negation && equalMemories(one.negated, other.negated)
is Sum -> other is Sum && equalMemories(one.augend, other.augend) && equalMemories(one.addend, other.addend)
is Difference -> other is Difference && equalMemories(one.minuend, other.minuend) && equalMemories(one.subtrahend, other.subtrahend)
is Product -> other is Product && equalMemories(one.multiplicand, other.multiplicand) && equalMemories(one.multiplier, other.multiplier)
is Quotient -> other is Quotient && equalMemories(one.dividend, other.dividend) && equalMemories(one.divisor, other.divisor)
is Endpoint -> one === other
}
interface WithMemorization {
val memory: OperationsMemory
}
fun equalMemories(one: WithMemorization, other: WithMemorization) : Boolean = equalMemories(one.memory, other.memory)

View File

@ -1,31 +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.test.misc
// TODO: Move to corresponding module "kmath-number-theory"
import kotlin.math.abs
data class BezoutIdentityWithGCD<T>(val first: T, val second: T, val gcd: T)
tailrec fun gcd(a: Long, b: Long): Long = if (a == 0L) abs(b) else gcd(b % a, a)
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)
}