From 403ff93f4af2960facb25696ae5fc1f50e428711 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Sat, 25 Jun 2022 16:01:18 +0300 Subject: [PATCH] Moved optimizations to branch refactor/polynomials --- .../kmath/functions/listUtilOptimized.kt | 250 ------------------ .../space/kscience/kmath/functions/misc.kt | 10 - 2 files changed, 260 deletions(-) delete mode 100644 kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtilOptimized.kt diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtilOptimized.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtilOptimized.kt deleted file mode 100644 index 6eb3a1dc7..000000000 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listUtilOptimized.kt +++ /dev/null @@ -1,250 +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.functions - -import space.kscience.kmath.operations.Ring -import space.kscience.kmath.operations.invoke -import kotlin.math.max -import kotlin.math.min - - -// TODO: Optimized copies of substitution and invocation -@UnstablePolynomialBoxingOptimization -@Suppress("NOTHING_TO_INLINE") -internal inline fun copyTo( - origin: List, - originDegree: Int, - target: MutableList, -) { - for (deg in 0 .. originDegree) target[deg] = origin[deg] -} - -@UnstablePolynomialBoxingOptimization -@Suppress("NOTHING_TO_INLINE") -internal inline fun multiplyAddingToUpdater( - ring: Ring, - multiplicand: MutableList, - multiplicandDegree: Int, - multiplier: List, - multiplierDegree: Int, - updater: MutableList, - zero: C, -) { - multiplyAddingTo( - ring = ring, - multiplicand = multiplicand, - multiplicandDegree = multiplicandDegree, - multiplier = multiplier, - multiplierDegree = multiplierDegree, - target = updater - ) - for (updateDeg in 0 .. multiplicandDegree + multiplierDegree) { - multiplicand[updateDeg] = updater[updateDeg] - updater[updateDeg] = zero - } -} - -@UnstablePolynomialBoxingOptimization -@Suppress("NOTHING_TO_INLINE") -internal inline fun multiplyAddingTo( - ring: Ring, - multiplicand: List, - multiplicandDegree: Int, - multiplier: List, - multiplierDegree: Int, - target: MutableList -) = ring { - for (d in 0 .. multiplicandDegree + multiplierDegree) - for (k in max(0, d - multiplierDegree)..min(multiplicandDegree, d)) - target[d] += multiplicand[k] * multiplier[d - k] -} - -@UnstablePolynomialBoxingOptimization -public fun ListPolynomial.substitute2(ring: Ring, arg: ListPolynomial) : ListPolynomial = ring { - if (coefficients.isEmpty()) return ListPolynomial(emptyList()) - - val thisDegree = coefficients.lastIndex - if (thisDegree == -1) return ListPolynomial(emptyList()) - val argDegree = arg.coefficients.lastIndex - if (argDegree == -1) return coefficients[0].asListPolynomial() - val constantZero = zero - val resultCoefs: MutableList = MutableList(thisDegree * argDegree + 1) { constantZero } - resultCoefs[0] = coefficients[thisDegree] - val resultCoefsUpdate: MutableList = MutableList(thisDegree * argDegree + 1) { constantZero } - var resultDegree = 0 - for (deg in thisDegree - 1 downTo 0) { - resultCoefsUpdate[0] = coefficients[deg] - multiplyAddingToUpdater( - ring = ring, - multiplicand = resultCoefs, - multiplicandDegree = resultDegree, - multiplier = arg.coefficients, - multiplierDegree = argDegree, - updater = resultCoefsUpdate, - zero = constantZero - ) - resultDegree += argDegree - } - - return ListPolynomial(resultCoefs) -} - -/** - * Returns numerator (polynomial) of rational function gotten by substitution rational function [arg] to the polynomial instance. - * More concrete, if [arg] is a fraction `f(x)/g(x)` and the receiving instance is `p(x)`, then - * ``` - * p(f/g) * g^deg(p) - * ``` - * is returned. - * - * Used in [ListPolynomial.substitute] and [ListRationalFunction.substitute] for performance optimisation. - */ // TODO: Дописать -@UnstablePolynomialBoxingOptimization -internal fun ListPolynomial.substituteRationalFunctionTakeNumerator(ring: Ring, arg: ListRationalFunction): ListPolynomial = ring { - if (coefficients.isEmpty()) return ListPolynomial(emptyList()) - - val thisDegree = coefficients.lastIndex - if (thisDegree == -1) return ListPolynomial(emptyList()) - val thisDegreeLog2 = 31 - thisDegree.countLeadingZeroBits() - val numeratorDegree = arg.numerator.coefficients.lastIndex - val denominatorDegree = arg.denominator.coefficients.lastIndex - val argDegree = max(numeratorDegree, denominatorDegree) - val constantZero = zero - val powersOf2 = buildList(thisDegreeLog2 + 1) { - var result = 1 - for (exp in 0 .. thisDegreeLog2) { - add(result) - result = result shl 1 - } - } - val hashes = powersOf2.runningReduce { acc, i -> acc + i } - val numeratorPowers = buildList>(thisDegreeLog2 + 1) { - add(arg.numerator.coefficients) - repeat(thisDegreeLog2) { - val next = MutableList(powersOf2[it + 1] * numeratorDegree + 1) { constantZero } - add(next) - val last = last() - multiplyAddingTo( - ring = ring, - multiplicand = last, - multiplicandDegree = powersOf2[it] * numeratorDegree + 1, - multiplier = last, - multiplierDegree = powersOf2[it] * numeratorDegree + 1, - target = next, - ) - } - } - val denominatorPowers = buildList>(thisDegreeLog2 + 1) { - add(arg.denominator.coefficients) - repeat(thisDegreeLog2) { - val next = MutableList(powersOf2[it + 1] * denominatorDegree + 1) { constantZero } - add(next) - val last = last() - multiplyAddingTo( - ring = ring, - multiplicand = last, - multiplicandDegree = powersOf2[it] * denominatorDegree + 1, - multiplier = last, - multiplierDegree = powersOf2[it] * denominatorDegree + 1, - target = next, - ) - } - } - val levelResultCoefsPool = buildList>(thisDegreeLog2 + 1) { - repeat(thisDegreeLog2 + 1) { - add(MutableList(hashes[it] * argDegree) { constantZero }) - } - } - val edgedMultiplier = MutableList(0) { TODO() } - val edgedMultiplierUpdater = MutableList(0) { TODO() } - - fun MutableList.reset() { - for (i in indices) set(i, constantZero) - } - - fun processLevel(level: Int, start: Int, end: Int) : List { - val levelResultCoefs = levelResultCoefsPool[level + 1] - - if (level == -1) { - levelResultCoefs[0] = coefficients[start] - } else { - levelResultCoefs.reset() - multiplyAddingTo( - ring = ring, - multiplicand = processLevel(level = level - 1, start = start, end = (start + end) / 2), - multiplicandDegree = hashes[level] * argDegree, - multiplier = denominatorPowers[level], - multiplierDegree = powersOf2[level] * denominatorDegree, - target = levelResultCoefs - ) - multiplyAddingTo( - ring = ring, - multiplicand = processLevel(level = level - 1, start = (start + end) / 2, end = end), - multiplicandDegree = hashes[level] * argDegree, - multiplier = numeratorPowers[level], - multiplierDegree = powersOf2[level] * numeratorDegree, - target = levelResultCoefs - ) - } - - return levelResultCoefs - } - - fun processLevelEdged(level: Int, start: Int, end: Int) : List { - val levelResultCoefs = levelResultCoefsPool[level + 1] - - if (level == -1) { - levelResultCoefs[0] = coefficients[start] - } else { - val levelsPowerOf2 = powersOf2[level] - if (end - start >= levelsPowerOf2) { - multiplyAddingTo( - ring = ring, - multiplicand = processLevelEdged(level = level - 1, start = start + levelsPowerOf2, end = end), - multiplicandDegree = hashes[level] * argDegree, // TODO: Ввести переменную - multiplier = numeratorPowers[level], - multiplierDegree = powersOf2[level] * numeratorDegree, - target = levelResultCoefs - ) - multiplyAddingTo( - ring = ring, - multiplicand = processLevel(level = level - 1, start = start, end = start + levelsPowerOf2), - multiplicandDegree = hashes[level] * argDegree, - multiplier = edgedMultiplier, - multiplierDegree = max((hashes[level] and thisDegree) - powersOf2[level] + 1, 0) * denominatorDegree, // TODO: Ввести переменную - target = levelResultCoefs - ) - if (level != thisDegreeLog2) { - multiplyAddingToUpdater( - ring = ring, - multiplicand = edgedMultiplier, - multiplicandDegree = max((hashes[level] and thisDegree) - powersOf2[level] + 1, 0) * denominatorDegree, // TODO: Ввести переменную - multiplier = denominatorPowers[level], - multiplierDegree = powersOf2[level] * denominatorDegree, - updater = edgedMultiplierUpdater, - zero = constantZero - ) - } - } else { - copyTo( - origin = processLevelEdged(level = level - 1, start = start + levelsPowerOf2, end = end), - originDegree = hashes[level] * argDegree, // TODO: Ввести переменную - target = levelResultCoefs - ) - } - } - - return levelResultCoefs - } - - return ListPolynomial( - processLevelEdged( - level = thisDegreeLog2, - start = 0, - end = thisDegree + 1 - ) - ) -} \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt index 7d6fc84fa..aba246519 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/misc.kt @@ -6,16 +6,6 @@ package space.kscience.kmath.functions -/** - * Marks operations that are going to be optimized reimplementations by reducing number of boxings but currently is - * under development and is not stable (or even ready to use). - */ -@RequiresOptIn( - message = "It's copy of operation with optimized boxing. It's currently unstable.", - level = RequiresOptIn.Level.ERROR -) -internal annotation class UnstablePolynomialBoxingOptimization - /** * Marks declarations that give access to internal entities of polynomials delicate structure. Thus, it allows to * optimize performance a bit by skipping standard steps, but such skips may cause critical errors if something is