From f86529d65944016631efe09218c4828feed32f03 Mon Sep 17 00:00:00 2001 From: Gleb Minaev <43728100+lounres@users.noreply.github.com> Date: Tue, 15 Mar 2022 15:35:17 +0300 Subject: [PATCH] Optimized `optimizedMultiply` and `optimizedAddMultiplied` for cases of negative value of `other` and `multiplier` --- .../kscience/kmath/functions/algebraicStub.kt | 59 +++++++++++++------ 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt index 9e5043b8c..3c37a01ec 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/algebraicStub.kt @@ -16,17 +16,11 @@ import space.kscience.kmath.operations.Group * @receiver the multiplicand. * @param other the multiplier. * @return the difference. + * @author Gleb Minaev */ -internal tailrec fun Group.optimizedMultiply(arg: C, other: Int): C = - when { - other == 0 -> zero - other == 1 -> arg - other == -1 -> -arg - other % 2 == 0 -> optimizedMultiply(arg + arg, other / 2) - other % 2 == 1 -> optimizedAddMultiplied(arg, arg + arg, other / 2) - other % 2 == -1 -> optimizedAddMultiplied(-arg, arg + arg, other / 2) - else -> error("Error in multiplication group instant by integer: got reminder by division by 2 different from 0, 1 and -1") - } +internal fun Group.optimizedMultiply(arg: C, other: Int): C = + if (other >= 0) optimizedMultiply(arg, other.toUInt()) + else optimizedMultiply(arg, (-other).toUInt()) // TODO: Move receiver to context receiver /** @@ -40,12 +34,43 @@ internal tailrec fun Group.optimizedMultiply(arg: C, other: Int): C = * @author Gleb Minaev */ internal tailrec fun Group.optimizedAddMultiplied(base: C, arg: C, multiplier: Int): C = + if (multiplier >= 0) optimizedAddMultiplied(base, arg, multiplier.toUInt()) + else optimizedAddMultiplied(base, arg, (-multiplier).toUInt()) + +// TODO: Move receiver to context receiver +/** + * Multiplication of element and integer. + * + * @receiver the multiplicand. + * @param other the multiplier. + * @return the difference. + * @author Gleb Minaev + */ +internal tailrec fun Group.optimizedMultiply(arg: C, other: UInt): C = when { - multiplier == 0 -> base - multiplier == 1 -> base + arg - multiplier == -1 -> base - arg - multiplier % 2 == 0 -> optimizedAddMultiplied(base, arg + arg, multiplier / 2) - multiplier % 2 == 1 -> optimizedAddMultiplied(base + arg, arg + arg, multiplier / 2) - multiplier % 2 == -1 -> optimizedAddMultiplied(base + arg, arg + arg, multiplier / 2) - else -> error("Error in multiplication group instant by integer: got reminder by division by 2 different from 0, 1 and -1") + other == 0u -> zero + other == 1u -> arg + other % 2u == 0u -> optimizedMultiply(arg + arg, other / 2u) + other % 2u == 1u -> optimizedAddMultiplied(arg, arg + arg, other / 2u) + else -> error("Error in multiplication group instant by unsigned integer: got reminder by division by 2 different from 0 and 1") + } + +// TODO: Move receiver to context receiver +/** + * Adds product of [arg] and [multiplier] to [base]. + * + * @receiver the algebra to provide multiplication. + * @param base the augend. + * @param arg the multiplicand. + * @param multiplier the multiplier. + * @return sum of the augend [base] and product of the multiplicand [arg] and the multiplier [multiplier]. + * @author Gleb Minaev + */ +internal tailrec fun Group.optimizedAddMultiplied(base: C, arg: C, multiplier: UInt): C = + when { + multiplier == 0u -> base + multiplier == 1u -> base + arg + multiplier % 2u == 0u -> optimizedAddMultiplied(base, arg + arg, multiplier / 2u) + multiplier % 2u == 1u -> optimizedAddMultiplied(base + arg, arg + arg, multiplier / 2u) + else -> error("Error in multiplication group instant by unsigned integer: got reminder by division by 2 different from 0 and 1") } \ No newline at end of file