From bb5e638b31186607bf953bff3bd2f5275f13e0c1 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 15 Mar 2022 20:38:27 +0300 Subject: [PATCH] Added polynomial spaces and scopes fabrics --- .../kmath/functions/labeledPolynomialUtil.kt | 189 +----------------- .../kmath/functions/numberedPolynomialUtil.kt | 189 +----------------- 2 files changed, 20 insertions(+), 358 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt index 9cf4f2652..5689f6e1b 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledPolynomialUtil.kt @@ -54,7 +54,7 @@ import kotlin.contracts.* // else -> multiplyWithPowerInternalLogic(base, arg, pow) // } // -//// Trivial but slow as duck +//// Trivial but very slow //context(LabeledPolynomialSpace) //internal tailrec fun > multiplyWithPowerInternalLogic(base: LabeledPolynomial, arg: LabeledPolynomial, exponent: UInt): LabeledPolynomial = // when { @@ -71,7 +71,15 @@ import kotlin.contracts.* // region Utilities -// TODO: Docs +/** + * Crates a [LabeledPolynomialSpace] over received ring. + */ +public fun > A.labeledPolynomial(): LabeledPolynomialSpace = + LabeledPolynomialSpace(this) + +/** + * Crates a [LabeledPolynomialSpace]'s scope over received ring. + */ @OptIn(ExperimentalContracts::class) public inline fun , R> A.labeledPolynomial(block: LabeledPolynomialSpace.() -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } @@ -254,64 +262,6 @@ public inline fun , R> A.labeledPolynomial(block: LabeledPolynomi //// region Field case // -//operator fun > Polynomial.div(other: Polynomial): Polynomial { -// if (other.isZero()) throw ArithmeticException("/ by zero") -// if (isZero()) return this -// -// fun Map, T>.leadingTerm() = -// this -// .asSequence() -// .map { Pair(it.key, it.value) } -// .reduce { (accDegs, accC), (listDegs, listC) -> -// for (i in 0..accDegs.lastIndex) { -// if (accDegs[i] > listDegs.getOrElse(i) { 0 }) return@reduce accDegs to accC -// if (accDegs[i] < listDegs.getOrElse(i) { 0 }) return@reduce listDegs to listC -// } -// if (accDegs.size < listDegs.size) listDegs to listC else accDegs to accC -// } -// -// var thisCoefficients = coefficients.toMutableMap() -// val otherCoefficients = other.coefficients -// val quotientCoefficients = HashMap, T>() -// -// var (thisLeadingTermDegs, thisLeadingTermC) = thisCoefficients.leadingTerm() -// val (otherLeadingTermDegs, otherLeadingTermC) = otherCoefficients.leadingTerm() -// -// while ( -// thisLeadingTermDegs.size >= otherLeadingTermDegs.size && -// (0..otherLeadingTermDegs.lastIndex).all { thisLeadingTermDegs[it] >= otherLeadingTermDegs[it] } -// ) { -// val multiplierDegs = -// thisLeadingTermDegs -// .mapIndexed { index, deg -> deg - otherLeadingTermDegs.getOrElse(index) { 0 } } -// .cleanUp() -// val multiplierC = thisLeadingTermC / otherLeadingTermC -// -// quotientCoefficients[multiplierDegs] = multiplierC -// -// for ((degs, t) in otherCoefficients) { -// val productDegs = -// (0..max(degs.lastIndex, multiplierDegs.lastIndex)) -// .map { degs.getOrElse(it) { 0 } + multiplierDegs.getOrElse(it) { 0 } } -// .cleanUp() -// val productC = t * multiplierC -// thisCoefficients[productDegs] = -// if (productDegs in thisCoefficients) thisCoefficients[productDegs]!! - productC else -productC -// } -// -// thisCoefficients = thisCoefficients.filterValues { it.isNotZero() }.toMutableMap() -// -// if (thisCoefficients.isEmpty()) -// return Polynomial(quotientCoefficients, toCheckInput = false) -// -// val t = thisCoefficients.leadingTerm() -// thisLeadingTermDegs = t.first -// thisLeadingTermC = t.second -// } -// -// return Polynomial(quotientCoefficients, toCheckInput = false) -//} -// //operator fun > Polynomial.div(other: T): Polynomial = // if (other.isZero()) throw ArithmeticException("/ by zero") // else @@ -321,125 +271,6 @@ public inline fun , R> A.labeledPolynomial(block: LabeledPolynomi // toCheckInput = false // ) // -//operator fun > Polynomial.rem(other: Polynomial): Polynomial { -// if (other.isZero()) throw ArithmeticException("/ by zero") -// if (isZero()) return this -// -// fun Map, T>.leadingTerm() = -// this -// .asSequence() -// .map { Pair(it.key, it.value) } -// .reduce { (accDegs, accC), (listDegs, listC) -> -// for (i in 0..accDegs.lastIndex) { -// if (accDegs[i] > listDegs.getOrElse(i) { 0 }) return@reduce accDegs to accC -// if (accDegs[i] < listDegs.getOrElse(i) { 0 }) return@reduce listDegs to listC -// } -// if (accDegs.size < listDegs.size) listDegs to listC else accDegs to accC -// } -// -// var thisCoefficients = coefficients.toMutableMap() -// val otherCoefficients = other.coefficients -// -// var (thisLeadingTermDegs, thisLeadingTermC) = thisCoefficients.leadingTerm() -// val (otherLeadingTermDegs, otherLeadingTermC) = otherCoefficients.leadingTerm() -// -// while ( -// thisLeadingTermDegs.size >= otherLeadingTermDegs.size && -// (0..otherLeadingTermDegs.lastIndex).all { thisLeadingTermDegs[it] >= otherLeadingTermDegs[it] } -// ) { -// val multiplierDegs = -// thisLeadingTermDegs -// .mapIndexed { index, deg -> deg - otherLeadingTermDegs.getOrElse(index) { 0 } } -// .cleanUp() -// val multiplierC = thisLeadingTermC / otherLeadingTermC -// -// for ((degs, t) in otherCoefficients) { -// val productDegs = -// (0..max(degs.lastIndex, multiplierDegs.lastIndex)) -// .map { degs.getOrElse(it) { 0 } + multiplierDegs.getOrElse(it) { 0 } } -// .cleanUp() -// val productC = t * multiplierC -// thisCoefficients[productDegs] = -// if (productDegs in thisCoefficients) thisCoefficients[productDegs]!! - productC else -productC -// } -// -// thisCoefficients = thisCoefficients.filterValues { it.isNotZero() }.toMutableMap() -// -// if (thisCoefficients.isEmpty()) -// return Polynomial(thisCoefficients, toCheckInput = false) -// -// val t = thisCoefficients.leadingTerm() -// thisLeadingTermDegs = t.first -// thisLeadingTermC = t.second -// } -// -// return Polynomial(thisCoefficients, toCheckInput = false) -//} -// -//infix fun > Polynomial.divrem(other: Polynomial): Polynomial.Companion.DividingResult { -// if (other.isZero()) throw ArithmeticException("/ by zero") -// if (isZero()) return Polynomial.Companion.DividingResult(this, this) -// -// fun Map, T>.leadingTerm() = -// this -// .asSequence() -// .map { Pair(it.key, it.value) } -// .reduce { (accDegs, accC), (listDegs, listC) -> -// for (i in 0..accDegs.lastIndex) { -// if (accDegs[i] > listDegs.getOrElse(i) { 0 }) return@reduce accDegs to accC -// if (accDegs[i] < listDegs.getOrElse(i) { 0 }) return@reduce listDegs to listC -// } -// if (accDegs.size < listDegs.size) listDegs to listC else accDegs to accC -// } -// -// var thisCoefficients = coefficients.toMutableMap() -// val otherCoefficients = other.coefficients -// val quotientCoefficients = HashMap, T>() -// -// var (thisLeadingTermDegs, thisLeadingTermC) = thisCoefficients.leadingTerm() -// val (otherLeadingTermDegs, otherLeadingTermC) = otherCoefficients.leadingTerm() -// -// while ( -// thisLeadingTermDegs.size >= otherLeadingTermDegs.size && -// (0..otherLeadingTermDegs.lastIndex).all { thisLeadingTermDegs[it] >= otherLeadingTermDegs[it] } -// ) { -// val multiplierDegs = -// thisLeadingTermDegs -// .mapIndexed { index, deg -> deg - otherLeadingTermDegs.getOrElse(index) { 0 } } -// .cleanUp() -// val multiplierC = thisLeadingTermC / otherLeadingTermC -// -// quotientCoefficients[multiplierDegs] = multiplierC -// -// for ((degs, t) in otherCoefficients) { -// val productDegs = -// (0..max(degs.lastIndex, multiplierDegs.lastIndex)) -// .map { degs.getOrElse(it) { 0 } + multiplierDegs.getOrElse(it) { 0 } } -// .cleanUp() -// val productC = t * multiplierC -// thisCoefficients[productDegs] = -// if (productDegs in thisCoefficients) thisCoefficients[productDegs]!! - productC else -productC -// } -// -// thisCoefficients = thisCoefficients.filterValues { it.isNotZero() }.toMutableMap() -// -// if (thisCoefficients.isEmpty()) -// return Polynomial.Companion.DividingResult( -// Polynomial(quotientCoefficients, toCheckInput = false), -// Polynomial(thisCoefficients, toCheckInput = false) -// ) -// -// val t = thisCoefficients.leadingTerm() -// thisLeadingTermDegs = t.first -// thisLeadingTermC = t.second -// } -// -// return Polynomial.Companion.DividingResult( -// Polynomial(quotientCoefficients, toCheckInput = false), -// Polynomial(thisCoefficients, toCheckInput = false) -// ) -//} -// //// endregion // endregion diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt index b7620e792..de95d0151 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedPolynomialUtil.kt @@ -38,7 +38,7 @@ import kotlin.jvm.JvmName // else -> multiplyWithPowerInternalLogic(base, arg, pow) // } // -//// Trivial but slow as duck +//// Trivial but very slow //context(NumberedPolynomialSpace) //internal tailrec fun > multiplyWithPowerInternalLogic(base: NumberedPolynomial, arg: NumberedPolynomial, exponent: UInt): NumberedPolynomial = // when { @@ -55,7 +55,15 @@ import kotlin.jvm.JvmName // region Utilities -// TODO: Docs +/** + * Crates a [NumberedPolynomialSpace] over received ring. + */ +public fun > A.numberedPolynomial(): NumberedPolynomialSpace = + NumberedPolynomialSpace(this) + +/** + * Crates a [NumberedPolynomialSpace]'s scope over received ring. + */ @OptIn(ExperimentalContracts::class) public inline fun , R> A.numberedPolynomial(block: NumberedPolynomialSpace.() -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } @@ -282,64 +290,6 @@ public inline fun , R> A.numberedPolynomial(block: NumberedPolyno //// region Field case // -//operator fun > Polynomial.div(other: Polynomial): Polynomial { -// if (other.isZero()) throw ArithmeticException("/ by zero") -// if (isZero()) return this -// -// fun Map, T>.leadingTerm() = -// this -// .asSequence() -// .map { Pair(it.key, it.value) } -// .reduce { (accDegs, accC), (listDegs, listC) -> -// for (i in 0..accDegs.lastIndex) { -// if (accDegs[i] > listDegs.getOrElse(i) { 0 }) return@reduce accDegs to accC -// if (accDegs[i] < listDegs.getOrElse(i) { 0 }) return@reduce listDegs to listC -// } -// if (accDegs.size < listDegs.size) listDegs to listC else accDegs to accC -// } -// -// var thisCoefficients = coefficients.toMutableMap() -// val otherCoefficients = other.coefficients -// val quotientCoefficients = HashMap, T>() -// -// var (thisLeadingTermDegs, thisLeadingTermC) = thisCoefficients.leadingTerm() -// val (otherLeadingTermDegs, otherLeadingTermC) = otherCoefficients.leadingTerm() -// -// while ( -// thisLeadingTermDegs.size >= otherLeadingTermDegs.size && -// (0..otherLeadingTermDegs.lastIndex).all { thisLeadingTermDegs[it] >= otherLeadingTermDegs[it] } -// ) { -// val multiplierDegs = -// thisLeadingTermDegs -// .mapIndexed { index, deg -> deg - otherLeadingTermDegs.getOrElse(index) { 0 } } -// .cleanUp() -// val multiplierC = thisLeadingTermC / otherLeadingTermC -// -// quotientCoefficients[multiplierDegs] = multiplierC -// -// for ((degs, t) in otherCoefficients) { -// val productDegs = -// (0..max(degs.lastIndex, multiplierDegs.lastIndex)) -// .map { degs.getOrElse(it) { 0 } + multiplierDegs.getOrElse(it) { 0 } } -// .cleanUp() -// val productC = t * multiplierC -// thisCoefficients[productDegs] = -// if (productDegs in thisCoefficients) thisCoefficients[productDegs]!! - productC else -productC -// } -// -// thisCoefficients = thisCoefficients.filterValues { it.isNotZero() }.toMutableMap() -// -// if (thisCoefficients.isEmpty()) -// return Polynomial(quotientCoefficients, toCheckInput = false) -// -// val t = thisCoefficients.leadingTerm() -// thisLeadingTermDegs = t.first -// thisLeadingTermC = t.second -// } -// -// return Polynomial(quotientCoefficients, toCheckInput = false) -//} -// //operator fun > Polynomial.div(other: T): Polynomial = // if (other.isZero()) throw ArithmeticException("/ by zero") // else @@ -349,125 +299,6 @@ public inline fun , R> A.numberedPolynomial(block: NumberedPolyno // toCheckInput = false // ) // -//operator fun > Polynomial.rem(other: Polynomial): Polynomial { -// if (other.isZero()) throw ArithmeticException("/ by zero") -// if (isZero()) return this -// -// fun Map, T>.leadingTerm() = -// this -// .asSequence() -// .map { Pair(it.key, it.value) } -// .reduce { (accDegs, accC), (listDegs, listC) -> -// for (i in 0..accDegs.lastIndex) { -// if (accDegs[i] > listDegs.getOrElse(i) { 0 }) return@reduce accDegs to accC -// if (accDegs[i] < listDegs.getOrElse(i) { 0 }) return@reduce listDegs to listC -// } -// if (accDegs.size < listDegs.size) listDegs to listC else accDegs to accC -// } -// -// var thisCoefficients = coefficients.toMutableMap() -// val otherCoefficients = other.coefficients -// -// var (thisLeadingTermDegs, thisLeadingTermC) = thisCoefficients.leadingTerm() -// val (otherLeadingTermDegs, otherLeadingTermC) = otherCoefficients.leadingTerm() -// -// while ( -// thisLeadingTermDegs.size >= otherLeadingTermDegs.size && -// (0..otherLeadingTermDegs.lastIndex).all { thisLeadingTermDegs[it] >= otherLeadingTermDegs[it] } -// ) { -// val multiplierDegs = -// thisLeadingTermDegs -// .mapIndexed { index, deg -> deg - otherLeadingTermDegs.getOrElse(index) { 0 } } -// .cleanUp() -// val multiplierC = thisLeadingTermC / otherLeadingTermC -// -// for ((degs, t) in otherCoefficients) { -// val productDegs = -// (0..max(degs.lastIndex, multiplierDegs.lastIndex)) -// .map { degs.getOrElse(it) { 0 } + multiplierDegs.getOrElse(it) { 0 } } -// .cleanUp() -// val productC = t * multiplierC -// thisCoefficients[productDegs] = -// if (productDegs in thisCoefficients) thisCoefficients[productDegs]!! - productC else -productC -// } -// -// thisCoefficients = thisCoefficients.filterValues { it.isNotZero() }.toMutableMap() -// -// if (thisCoefficients.isEmpty()) -// return Polynomial(thisCoefficients, toCheckInput = false) -// -// val t = thisCoefficients.leadingTerm() -// thisLeadingTermDegs = t.first -// thisLeadingTermC = t.second -// } -// -// return Polynomial(thisCoefficients, toCheckInput = false) -//} -// -//infix fun > Polynomial.divrem(other: Polynomial): Polynomial.Companion.DividingResult { -// if (other.isZero()) throw ArithmeticException("/ by zero") -// if (isZero()) return Polynomial.Companion.DividingResult(this, this) -// -// fun Map, T>.leadingTerm() = -// this -// .asSequence() -// .map { Pair(it.key, it.value) } -// .reduce { (accDegs, accC), (listDegs, listC) -> -// for (i in 0..accDegs.lastIndex) { -// if (accDegs[i] > listDegs.getOrElse(i) { 0 }) return@reduce accDegs to accC -// if (accDegs[i] < listDegs.getOrElse(i) { 0 }) return@reduce listDegs to listC -// } -// if (accDegs.size < listDegs.size) listDegs to listC else accDegs to accC -// } -// -// var thisCoefficients = coefficients.toMutableMap() -// val otherCoefficients = other.coefficients -// val quotientCoefficients = HashMap, T>() -// -// var (thisLeadingTermDegs, thisLeadingTermC) = thisCoefficients.leadingTerm() -// val (otherLeadingTermDegs, otherLeadingTermC) = otherCoefficients.leadingTerm() -// -// while ( -// thisLeadingTermDegs.size >= otherLeadingTermDegs.size && -// (0..otherLeadingTermDegs.lastIndex).all { thisLeadingTermDegs[it] >= otherLeadingTermDegs[it] } -// ) { -// val multiplierDegs = -// thisLeadingTermDegs -// .mapIndexed { index, deg -> deg - otherLeadingTermDegs.getOrElse(index) { 0 } } -// .cleanUp() -// val multiplierC = thisLeadingTermC / otherLeadingTermC -// -// quotientCoefficients[multiplierDegs] = multiplierC -// -// for ((degs, t) in otherCoefficients) { -// val productDegs = -// (0..max(degs.lastIndex, multiplierDegs.lastIndex)) -// .map { degs.getOrElse(it) { 0 } + multiplierDegs.getOrElse(it) { 0 } } -// .cleanUp() -// val productC = t * multiplierC -// thisCoefficients[productDegs] = -// if (productDegs in thisCoefficients) thisCoefficients[productDegs]!! - productC else -productC -// } -// -// thisCoefficients = thisCoefficients.filterValues { it.isNotZero() }.toMutableMap() -// -// if (thisCoefficients.isEmpty()) -// return Polynomial.Companion.DividingResult( -// Polynomial(quotientCoefficients, toCheckInput = false), -// Polynomial(thisCoefficients, toCheckInput = false) -// ) -// -// val t = thisCoefficients.leadingTerm() -// thisLeadingTermDegs = t.first -// thisLeadingTermC = t.second -// } -// -// return Polynomial.Companion.DividingResult( -// Polynomial(quotientCoefficients, toCheckInput = false), -// Polynomial(thisCoefficients, toCheckInput = false) -// ) -//} -// //// endregion // endregion