diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt index 411409e39..80998d6bf 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedPolynomial.kt @@ -5,6 +5,7 @@ package space.kscience.kmath.functions +import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.ScaleOperations import kotlin.contracts.InvocationKind @@ -132,7 +133,59 @@ public fun > NumberedPolynomialSpace.NumberedPolynomial(vara //context(NumberedPolynomialSpace) //public fun > Symbol.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(mapOf(this to 1u) to constantOne)) -public fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(emptyList() to this)) +//context(A) +//public fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(emptyList() to this)) + +@DslMarker +internal annotation class NumberedPolynomialConstructorDSL + +@NumberedPolynomialConstructorDSL +public class NumberedPolynomialTermSignatureBuilder { + private val signature: MutableList = ArrayList() + public fun build(): List = signature + public infix fun Int.inPowerOf(deg: UInt) { + if (this > signature.lastIndex) { + signature.addAll(List(this - signature.lastIndex - 1) { 0u }) + signature.add(deg) + } else { + signature[this] = deg + } + } + public infix fun Int.to(deg: UInt): Unit = this inPowerOf deg +} + +@NumberedPolynomialConstructorDSL +public class NumberedPolynomialBuilderOverRing internal constructor(internal val context: Ring, capacity: Int = 0) { + private val coefficients: MutableMap, C> = LinkedHashMap(capacity) + public fun build(): NumberedPolynomial = NumberedPolynomial(coefficients) + public operator fun C.invoke(block: NumberedPolynomialTermSignatureBuilder.() -> Unit) { + val signature = NumberedPolynomialTermSignatureBuilder().apply(block).build() + coefficients[signature] = context { coefficients.getOrElse(signature) { zero } + this@invoke } + } +} + +@NumberedPolynomialConstructorDSL +public class NumberedPolynomialBuilderOverPolynomialSpace internal constructor(internal val context: NumberedPolynomialSpace, capacity: Int = 0) { + private val coefficients: MutableMap, C> = LinkedHashMap(capacity) + public fun build(): NumberedPolynomial = NumberedPolynomial(coefficients) + public operator fun C.invoke(block: NumberedPolynomialTermSignatureBuilder.() -> Unit) { + val signature = NumberedPolynomialTermSignatureBuilder().apply(block).build() + coefficients[signature] = context { coefficients.getOrElse(signature) { constantZero } + this@invoke } + } +} + +@NumberedPolynomialConstructorDSL +@Suppress("FunctionName") +public fun > A.NumberedPolynomial(block: NumberedPolynomialBuilderOverRing.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilderOverRing(this).apply(block).build() +@NumberedPolynomialConstructorDSL +@Suppress("FunctionName") +public fun > A.NumberedPolynomial(capacity: Int, block: NumberedPolynomialBuilderOverRing.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilderOverRing(this, capacity).apply(block).build() +@NumberedPolynomialConstructorDSL +@Suppress("FunctionName") +public fun > NumberedPolynomialSpace.NumberedPolynomial(block: NumberedPolynomialBuilderOverPolynomialSpace.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilderOverPolynomialSpace(this).apply(block).build() +@NumberedPolynomialConstructorDSL +@Suppress("FunctionName") +public fun > NumberedPolynomialSpace.NumberedPolynomial(capacity: Int, block: NumberedPolynomialBuilderOverPolynomialSpace.() -> Unit) : NumberedPolynomial = NumberedPolynomialBuilderOverPolynomialSpace(this, capacity).apply(block).build() /** * Space of polynomials. @@ -604,4 +657,7 @@ public open class NumberedPolynomialSpace>( for ((degs, c) in this) if (c.isZero()) this.remove(degs) } } + + // TODO: Move to other constructors with context receiver + public fun C.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(emptyList() to this)) } \ No newline at end of file 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 27fdd7d7b..88d357413 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 @@ -17,53 +17,6 @@ import kotlin.contracts.contract // TODO: Docs -//// TODO: Reuse underlying ring extensions -// -//context(LabeledPolynomialSpace) -//@Suppress("NOTHING_TO_INLINE") -//fun > numberConstant(value: Int): C = ring { number(value) } -// -//context(LabeledPolynomialSpace) -//fun > power(arg: C, pow: UInt): C = ring { power(arg, pow) } -// -//context(LabeledPolynomialSpace) -//fun > multiplyWithPower(base: C, arg: C, pow: UInt): C = ring { multiplyWithPower(base, arg, pow) } -// - -// -//context(LabeledPolynomialSpace) -//fun > power(arg: Symbol, pow: UInt): LabeledPolynomial = -// if (pow == 0U) one -// else LabeledPolynomial(mapOf( -// mapOf(arg to pow) to constantOne -// )) -// - -// -//context(LabeledPolynomialSpace) -//fun > number(value: Int): LabeledPolynomial = ring { LabeledPolynomial(mapOf(emptyMap() to number(value))) } -// -//context(LabeledPolynomialSpace) -//fun > multiplyWithPower(base: LabeledPolynomial, arg: LabeledPolynomial, pow: UInt): LabeledPolynomial = -// when { -// arg.isZero() && pow > 0U -> base -// arg.isOne() -> base -// arg.isMinusOne() -> if (pow % 2U == 0U) base else -base -// else -> multiplyWithPowerInternalLogic(base, arg, pow) -// } -// -//// Trivial but very slow -//context(LabeledPolynomialSpace) -//internal tailrec fun > multiplyWithPowerInternalLogic(base: LabeledPolynomial, arg: LabeledPolynomial, exponent: UInt): LabeledPolynomial = -// when { -// exponent == 0U -> base -// exponent == 1U -> base * arg -// exponent % 2U == 0U -> multiplyWithPowerInternalLogic(base, arg * arg, exponent / 2U) -// exponent % 2U == 1U -> multiplyWithPowerInternalLogic(base * arg, arg * arg, exponent / 2U) -// else -> error("Error in raising ring instant by unsigned integer: got reminder by division by 2 different from 0 and 1") -// } -// - /** * Creates a [LabeledPolynomialSpace] over a received ring. */ diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt index df5ba593a..35155d09d 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listPolynomialUtil.kt @@ -124,7 +124,7 @@ public fun ListPolynomial.substitute(ring: Ring, arg: ListPolynomial = MutableList(thisDegree * argDegree + 1) { constantZero } resultCoefs[0] = coefficients[thisDegree]