Feature: Polynomials and rational functions #469

Merged
lounres merged 132 commits from feature/polynomials into dev 2022-07-28 18:04:06 +03:00
4 changed files with 3321 additions and 76 deletions
Showing only changes of commit 672a3c1552 - Show all commits

View File

@ -121,7 +121,7 @@ class ListPolynomialUtilTest {
}
@Test
@Ignore // FIXME: This tests work only for sane realisations of the substitutions. Currently, it is not.
// Sane algorithm for substitution p(q/r) (p, q, and r are polynomials) should make denominator r^deg(p),
// Sane algorithm for substitution p(q/r) (p, q, and r are polynomials) should return denominator r^deg(p),
// not r^(deg(p)(deg(p)+1)/2) as it is now.
fun test_Polynomial_substitute_RationalFunction() {
assertEquals(
@ -589,7 +589,7 @@ class ListPolynomialUtilTest {
}
@Test
@Ignore // FIXME: This tests work only for sane realisations of the substitutions. Currently, it is not.
// Sane algorithm for substitution p(q/r) (p, q, and r are polynomials) should make denominator r^deg(p),
// Sane algorithm for substitution p(q/r) (p, q, and r are polynomials) should return denominator r^deg(p),
// not r^(deg(p)(deg(p)+1)/2) as it is now.
fun test_RationalFunction_substitute_RationalFunction() {
assertEquals(

View File

@ -41,66 +41,105 @@ class Rational {
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: Rational): Rational {
val denominatorsGcd = gcd(denominator, other.denominator)
val dividedThisDenominator = denominator / denominatorsGcd
val dividedOtherDenominator = other.denominator / denominatorsGcd
val numeratorCandidate = numerator * dividedOtherDenominator + dividedThisDenominator * other.numerator
val secondGcd = gcd(numeratorCandidate, denominatorsGcd)
return Rational(
numeratorCandidate / secondGcd,
dividedThisDenominator * (other.denominator / secondGcd),
toCheckInput = false
)
}
operator fun plus(other: Int): Rational =
Rational(
numerator + denominator * other.toLong(),
denominator
denominator,
toCheckInput = false
)
operator fun plus(other: Long): Rational =
Rational(
numerator + denominator * other,
denominator
denominator,
toCheckInput = false
)
operator fun minus(other: Rational): Rational =
Rational(
numerator * other.denominator - denominator * other.numerator,
denominator * other.denominator
operator fun minus(other: Rational): Rational {
val denominatorsGcd = gcd(denominator, other.denominator)
val dividedThisDenominator = denominator / denominatorsGcd
val dividedOtherDenominator = other.denominator / denominatorsGcd
val numeratorCandidate = numerator * dividedOtherDenominator - dividedThisDenominator * other.numerator
val secondGcd = gcd(numeratorCandidate, denominatorsGcd)
return Rational(
numeratorCandidate / secondGcd,
dividedThisDenominator * (other.denominator / secondGcd),
toCheckInput = false
)
}
operator fun minus(other: Int): Rational =
Rational(
numerator - denominator * other.toLong(),
denominator
denominator,
toCheckInput = false
)
operator fun minus(other: Long): Rational =
Rational(
numerator - denominator * other,
denominator
denominator,
toCheckInput = false
)
operator fun times(other: Rational): Rational =
Rational(
numerator * other.numerator,
denominator * other.denominator
operator fun times(other: Rational): Rational {
val thisDenominatorAndOtherNumeratorGcd = gcd(denominator, other.numerator)
val otherDenominatorAndThisNumeratorGcd = gcd(other.denominator, numerator)
return Rational(
(numerator / otherDenominatorAndThisNumeratorGcd) * (other.numerator / thisDenominatorAndOtherNumeratorGcd),
(denominator / thisDenominatorAndOtherNumeratorGcd) * (other.denominator / otherDenominatorAndThisNumeratorGcd),
toCheckInput = false
)
operator fun times(other: Int): Rational =
Rational(
numerator * other.toLong(),
denominator
}
operator fun times(other: Int): Rational {
val other = other.toLong()
val denominatorAndOtherGcd = gcd(denominator, other)
return Rational(
numerator * (other / denominatorAndOtherGcd),
denominator / denominatorAndOtherGcd,
toCheckInput = false
)
operator fun times(other: Long): Rational =
Rational(
numerator * other,
denominator
}
operator fun times(other: Long): Rational {
val denominatorAndOtherGcd = gcd(denominator, other)
return Rational(
numerator * (other / denominatorAndOtherGcd),
denominator / denominatorAndOtherGcd,
toCheckInput = false
)
operator fun div(other: Rational): Rational =
Rational(
numerator * other.denominator,
denominator * other.numerator
}
operator fun div(other: Rational): Rational {
val denominatorsGcd = gcd(denominator, other.denominator)
val numeratorsGcd = gcd(numerator, other.numerator)
return Rational(
(numerator / numeratorsGcd) * (other.denominator / denominatorsGcd),
(denominator / denominatorsGcd) * (other.numerator / numeratorsGcd)
)
operator fun div(other: Int): Rational =
Rational(
numerator,
denominator * other.toLong()
}
operator fun div(other: Int): Rational {
val other = other.toLong()
val numeratorAndOtherGcd = gcd(numerator, other)
return Rational(
numerator / numeratorAndOtherGcd,
denominator * (other / numeratorAndOtherGcd),
toCheckInput = false
)
operator fun div(other: Long): Rational =
Rational(
numerator,
denominator * other
}
operator fun div(other: Long): Rational {
val numeratorAndOtherGcd = gcd(numerator, other)
return Rational(
numerator / numeratorAndOtherGcd,
denominator * (other / numeratorAndOtherGcd),
toCheckInput = false
)
}
override fun equals(other: Any?): Boolean =
when (other) {
is Rational -> numerator == other.numerator && denominator == other.denominator

View File

@ -5,6 +5,8 @@
package space.kscience.kmath.test.misc
import space.kscience.kmath.functions.NumberedPolynomial
import space.kscience.kmath.functions.NumberedRationalFunction
import kotlin.test.assertEquals
@ -12,3 +14,35 @@ fun <T> assertContentEquals(expected: Map<T, Double>, actual: Map<T, Double>, ab
assertEquals(expected.keys, actual.keys, message)
for ((key, expectedValue) in expected) assertEquals(expectedValue, actual[key]!!, absoluteTolerance, message)
}
fun assertEquals(
expected: NumberedPolynomial<Double>,
actual: NumberedPolynomial<Double>,
absoluteTolerance: Double,
message: String? = null
) = assertContentEquals(
expected.coefficients,
actual.coefficients,
absoluteTolerance,
message
)
fun assertEquals(
expected: NumberedRationalFunction<Double>,
actual: NumberedRationalFunction<Double>,
absoluteTolerance: Double,
message: String? = null
) {
assertEquals(
expected.numerator,
actual.numerator,
absoluteTolerance,
message
)
assertEquals(
expected.denominator,
actual.denominator,
absoluteTolerance,
message
)
}