diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt index 908e89534..b904f7331 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledPolynomial.kt @@ -8,10 +8,6 @@ package space.kscience.kmath.functions import space.kscience.kmath.expressions.Symbol import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.ScaleOperations -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract -import kotlin.experimental.ExperimentalTypeInference -import kotlin.jvm.JvmName import kotlin.math.max @@ -49,98 +45,6 @@ internal constructor( override fun toString(): String = "LabeledPolynomial$coefficients" } -/** - * Returns the same degrees' description of the monomial, but without zero degrees. - */ -internal fun Map.cleanUp() = filterValues { it > 0U } - -// Waiting for context receivers :( TODO: Replace with context receivers when they will be available - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(coefs, toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(coefs, toCheckInput) -@Suppress("FunctionName") -internal fun > A.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial { - if (!toCheckInput) return LabeledPolynomial(coefs) - - val fixedCoefs = mutableMapOf, C>() - - for (entry in coefs) { - val key = entry.key.cleanUp() - val value = entry.value - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return LabeledPolynomial(fixedCoefs) -} - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs, toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs, toCheckInput) -@Suppress("FunctionName") -internal fun > A.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial { - if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) - - val fixedCoefs = mutableMapOf, C>() - - for (entry in pairs) { - val key = entry.first.cleanUp() - val value = entry.second - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return LabeledPolynomial(fixedCoefs) -} - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs = pairs, toCheckInput = toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs = pairs, toCheckInput = toCheckInput) -@Suppress("FunctionName") -internal fun > A.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial { - if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) - - val fixedCoefs = mutableMapOf, C>() - - for (entry in pairs) { - val key = entry.first.cleanUp() - val value = entry.second - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return LabeledPolynomial(fixedCoefs) -} - -@Suppress("FunctionName") -public fun > A.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledPolynomialSpace.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) - -@Suppress("FunctionName") -public fun > A.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledPolynomialSpace.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) - -@Suppress("FunctionName") -public fun > A.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledPolynomialSpace.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) - -//context(A) -//public fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to one)) -//context(LabeledPolynomialSpace) -//public fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to constantOne)) - -public fun C.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to this)) - /** * Space of polynomials. * diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt index 0f46520dc..76c6874f5 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/LabeledRationalFunction.kt @@ -17,39 +17,6 @@ public class LabeledRationalFunction( override fun toString(): String = "LabeledRationalFunction${numerator.coefficients}/${denominator.coefficients}" } -// Waiting for context receivers :( TODO: Replace with context receivers when they will be available - -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): LabeledRationalFunction = - LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients, toCheckInput = true), - LabeledPolynomial(denominatorCoefficients, toCheckInput = true) - ) -@Suppress("FunctionName") -public fun > A.LabeledRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): LabeledRationalFunction = - LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients, toCheckInput = true), - LabeledPolynomial(denominatorCoefficients, toCheckInput = true) - ) -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numerator: LabeledPolynomial): LabeledRationalFunction = - LabeledRationalFunction(numerator, polynomialOne) -@Suppress("FunctionName") -public fun > A.LabeledRationalFunction(numerator: LabeledPolynomial): LabeledRationalFunction = - LabeledRationalFunction(numerator, LabeledPolynomial(mapOf(emptyMap() to one), toCheckInput = false)) -@Suppress("FunctionName") -public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numeratorCoefficients: Map, C>): LabeledRationalFunction = - LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients, toCheckInput = true), - polynomialOne - ) -@Suppress("FunctionName") -public fun > A.LabeledRationalFunction(numeratorCoefficients: Map, C>): LabeledRationalFunction = - LabeledRationalFunction( - LabeledPolynomial(numeratorCoefficients, toCheckInput = true), - LabeledPolynomial(mapOf(emptyMap() to one), toCheckInput = false) - ) - public class LabeledRationalFunctionSpace>( public val ring: A, ) : diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt index 711d2bb49..585da95ea 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListPolynomial.kt @@ -50,24 +50,6 @@ public data class ListPolynomial( override fun toString(): String = "Polynomial$coefficients" } -/** - * Returns a [ListPolynomial] instance with given [coefficients]. The collection of coefficients will be reversed if - * [reverse] parameter is true. - */ -@Suppress("FunctionName") -public fun ListPolynomial(coefficients: List, reverse: Boolean = false): ListPolynomial = - ListPolynomial(with(coefficients) { if (reverse) reversed() else this }) - -/** - * Returns a [ListPolynomial] instance with given [coefficients]. The collection of coefficients will be reversed if - * [reverse] parameter is true. - */ -@Suppress("FunctionName") -public fun ListPolynomial(vararg coefficients: C, reverse: Boolean = false): ListPolynomial = - ListPolynomial(with(coefficients) { if (reverse) reversed() else toList() }) - -public fun C.asListPolynomial() : ListPolynomial = ListPolynomial(listOf(this)) - /** * Space of univariate polynomials constructed over ring. * diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt index f62d1857f..7b6c23ac3 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/ListRationalFunction.kt @@ -15,39 +15,6 @@ public data class ListRationalFunction( override fun toString(): String = "RationalFunction${numerator.coefficients}/${denominator.coefficients}" } -// Waiting for context receivers :( TODO: Replace with context receivers when they will be available - -@Suppress("FunctionName") -public fun > ListRationalFunctionSpace.ListRationalFunction(numeratorCoefficients: List, denominatorCoefficients: List, reverse: Boolean = false): ListRationalFunction = - ListRationalFunction( - ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), - ListPolynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } ) - ) -@Suppress("FunctionName") -public fun > A.ListRationalFunction(numeratorCoefficients: List, denominatorCoefficients: List, reverse: Boolean = false): ListRationalFunction = - ListRationalFunction( - ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), - ListPolynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } ) - ) -@Suppress("FunctionName") -public fun > ListRationalFunctionSpace.ListRationalFunction(numerator: ListPolynomial): ListRationalFunction = - ListRationalFunction(numerator, polynomialOne) -@Suppress("FunctionName") -public fun > A.ListRationalFunction(numerator: ListPolynomial): ListRationalFunction = - ListRationalFunction(numerator, ListPolynomial(listOf(one))) -@Suppress("FunctionName") -public fun > ListRationalFunctionSpace.ListRationalFunction(numeratorCoefficients: List, reverse: Boolean = false): ListRationalFunction = - ListRationalFunction( - ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), - polynomialOne - ) -@Suppress("FunctionName") -public fun > A.ListRationalFunction(numeratorCoefficients: List, reverse: Boolean = false): ListRationalFunction = - ListRationalFunction( - ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), - ListPolynomial(listOf(one)) - ) - public class ListRationalFunctionSpace> ( public val ring: A, ) : 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 f931e8e7e..e75373819 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 @@ -49,152 +49,6 @@ internal constructor( override fun toString(): String = "NumberedPolynomial$coefficients" } -/** - * Returns the same degrees' description of the monomial, but without extra zero degrees on the end. - */ -internal fun List.cleanUp() = subList(0, indexOfLast { it != 0U } + 1) - -// Waiting for context receivers :( TODO: Replace with context receivers when they will be available - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(coefs, toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(coefs, toCheckInput) -@Suppress("FunctionName") -internal fun > A.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial { - if (!toCheckInput) return NumberedPolynomial(coefs) - - val fixedCoefs = mutableMapOf, C>() - - for (entry in coefs) { - val key = entry.key.cleanUp() - val value = entry.value - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return NumberedPolynomial(fixedCoefs) -} - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs, toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs, toCheckInput) -@Suppress("FunctionName") -internal fun > A.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial { - if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) - - val fixedCoefs = mutableMapOf, C>() - - for (entry in pairs) { - val key = entry.first.cleanUp() - val value = entry.second - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return NumberedPolynomial(fixedCoefs) -} - -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs = pairs, toCheckInput = toCheckInput) -@Suppress("FunctionName", "NOTHING_TO_INLINE") -internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs = pairs, toCheckInput = toCheckInput) -@Suppress("FunctionName") -internal fun > A.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial { - if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) - - val fixedCoefs = mutableMapOf, C>() - - for (entry in pairs) { - val key = entry.first.cleanUp() - val value = entry.second - fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value - } - - return NumberedPolynomial(fixedCoefs) -} - -@Suppress("FunctionName") -public fun > A.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedPolynomialSpace.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) - -@Suppress("FunctionName") -public fun > A.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedPolynomialSpace.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) - -@Suppress("FunctionName") -public fun > A.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedPolynomialSpace.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) - -//context(A) -//public fun > Symbol.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(mapOf(this to 1u) to one)) -//context(NumberedPolynomialSpace) -//public fun > Symbol.asNumberedPolynomial() : NumberedPolynomial = NumberedPolynomial(mapOf(mapOf(this to 1u) to constantOne)) - -//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.pow(deg: UInt): Unit = this inPowerOf deg - public infix fun Int.of(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 } - } - public infix fun C.with(block: NumberedPolynomialTermSignatureBuilder.() -> Unit): Unit = this.invoke(block) -} - -@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. * @@ -530,6 +384,6 @@ public open class NumberedPolynomialSpace>( @JvmName("invokePolynomial") public inline operator fun NumberedPolynomial.invoke(argument: Map>): NumberedPolynomial = this.substitute(ring, argument) - // TODO: Move to other constructors with context receiver + // FIXME: 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/NumberedRationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt index b4d9f1d91..30c7f0188 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/NumberedRationalFunction.kt @@ -17,39 +17,6 @@ public class NumberedRationalFunction internal constructor( override fun toString(): String = "NumberedRationalFunction${numerator.coefficients}/${denominator.coefficients}" } -// Waiting for context receivers :( TODO: Replace with context receivers when they will be available - -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): NumberedRationalFunction = - NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients, toCheckInput = true), - NumberedPolynomial(denominatorCoefficients, toCheckInput = true) - ) -@Suppress("FunctionName") -public fun > A.NumberedRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): NumberedRationalFunction = - NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients, toCheckInput = true), - NumberedPolynomial(denominatorCoefficients, toCheckInput = true) - ) -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numerator: NumberedPolynomial): NumberedRationalFunction = - NumberedRationalFunction(numerator, polynomialOne) -@Suppress("FunctionName") -public fun > A.NumberedRationalFunction(numerator: NumberedPolynomial): NumberedRationalFunction = - NumberedRationalFunction(numerator, NumberedPolynomial(mapOf(emptyList() to one), toCheckInput = false)) -@Suppress("FunctionName") -public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numeratorCoefficients: Map, C>): NumberedRationalFunction = - NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients, toCheckInput = true), - polynomialOne - ) -@Suppress("FunctionName") -public fun > A.NumberedRationalFunction(numeratorCoefficients: Map, C>): NumberedRationalFunction = - NumberedRationalFunction( - NumberedPolynomial(numeratorCoefficients, toCheckInput = true), - NumberedPolynomial(mapOf(emptyList() to one), toCheckInput = false) - ) - public class NumberedRationalFunctionSpace> ( public val ring: A, ) : diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt index 374f4a936..eede543ee 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/RationalFunction.kt @@ -27,7 +27,7 @@ public interface RationalFunction> { * @param C the type of constants. Polynomials have them as coefficients in their terms. * @param P the type of polynomials. Rational functions have them as numerators and denominators in them. * @param R the type of rational functions. - */ // TODO: Add support of field + */ @Suppress("INAPPLICABLE_JVM_NAME", "PARAMETER_NAME_CHANGED_ON_OVERRIDE") public interface RationalFunctionalSpace, R: RationalFunction> : Ring { /** @@ -457,7 +457,7 @@ public interface RationalFunctionalSpace, R: RationalFunctio * @param P the type of polynomials. Rational functions have them as numerators and denominators in them. * @param R the type of rational functions. * @param A the type of algebraic structure (precisely, of ring) provided for constants. - */ // TODO: Add support of field + */ @Suppress("INAPPLICABLE_JVM_NAME") public interface RationalFunctionalSpaceOverRing, R: RationalFunction, A: Ring> : RationalFunctionalSpace { @@ -551,7 +551,7 @@ public interface RationalFunctionalSpaceOverRing, R: Rationa * @param P the type of polynomials. Rational functions have them as numerators and denominators in them. * @param R the type of rational functions. * @param AP the type of algebraic structure (precisely, of ring) provided for polynomials. - */ // TODO: Add support of field + */ @Suppress("INAPPLICABLE_JVM_NAME") public interface RationalFunctionalSpaceOverPolynomialSpace< C, @@ -779,8 +779,7 @@ public interface RationalFunctionalSpaceOverPolynomialSpace< * @param C the type of constants. Polynomials have them as coefficients in their terms. * @param P the type of polynomials. Rational functions have them as numerators and denominators in them. * @param R the type of rational functions. - * @param AP the type of algebraic structure (precisely, of ring) provided for polynomials. - */ // TODO: Add support of field + */ @Suppress("INAPPLICABLE_JVM_NAME") public abstract class PolynomialSpaceOfFractions< C, 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 ca93e4259..fa97d6a6c 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 @@ -9,7 +9,7 @@ import space.kscience.kmath.operations.* // TODO: All of this should be moved to algebraic structures' place for utilities -// TODO: Move receiver to context receiver +// FIXME: Move receiver to context receiver /** * Returns product of [arg] and integer [multiplier]. * @@ -22,7 +22,7 @@ internal fun Group.multiplyBySquaring(arg: C, multiplier: Int): C = if (multiplier >= 0) multiplyBySquaring(arg, multiplier.toUInt()) else multiplyBySquaring(-arg, (-multiplier).toUInt()) -// TODO: Move receiver to context receiver +// FIXME: Move receiver to context receiver /** * Adds product of [arg] and [multiplier] to [base]. * @@ -36,7 +36,7 @@ internal fun GroupOps.addMultipliedBySquaring(base: C, arg: C, multiplier if (multiplier >= 0) addMultipliedBySquaring(base, arg, multiplier.toUInt()) else addMultipliedBySquaring(base, -arg, (-multiplier).toUInt()) -// TODO: Move receiver to context receiver +// FIXME: Move receiver to context receiver /** * Returns product of [arg] and integer [multiplier]. * @@ -56,7 +56,7 @@ internal tailrec fun Group.multiplyBySquaring(arg: C, multiplier: UInt): 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 +// FIXME: Move receiver to context receiver /** * Adds product of [arg] and [multiplier] to [base]. * @@ -77,7 +77,7 @@ internal tailrec fun GroupOps.addMultipliedBySquaring(base: C, arg: C, mu 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 +// FIXME: Move receiver to context receiver /** * Raises [arg] to the integer power [exponent]. * @@ -90,7 +90,7 @@ internal fun Field.exponentiationBySquaring(arg: C, exponent: Int): C = if (exponent >= 0) exponentiationBySquaring(arg, exponent.toUInt()) else exponentiationBySquaring(one / arg, (-exponent).toUInt()) -// TODO: Move receiver to context receiver +// FIXME: Move receiver to context receiver /** * Multiplies [base] and [arg] raised to the integer power [exponent]. * @@ -104,7 +104,7 @@ internal fun Field.multiplyExponentiationBySquaring(base: C, arg: C, expo if (exponent >= 0) multiplyExponentiationBySquaring(base, arg, exponent.toUInt()) else multiplyExponentiationBySquaring(base, one / arg, (-exponent).toUInt()) -// TODO: Move receiver to context receiver +// FIXME: Move receiver to context receiver /** * Raises [arg] to the integer power [exponent]. * @@ -124,7 +124,7 @@ internal tailrec fun Ring.exponentiationBySquaring(arg: C, exponent: UInt 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 +// FIXME: Move receiver to context receiver /** * Multiplies [base] and [arg] raised to the integer power [exponent]. * diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt new file mode 100644 index 000000000..12688a865 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/labeledConstructors.kt @@ -0,0 +1,147 @@ +/* + * 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.expressions.Symbol +import space.kscience.kmath.operations.Ring + + +/** + * Returns the same degrees' description of the monomial, but without zero degrees. + */ +internal fun Map.cleanUp() = filterValues { it > 0U } + +// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available + +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(coefs, toCheckInput) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(coefs, toCheckInput) +@Suppress("FunctionName") +internal fun > A.LabeledPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : LabeledPolynomial { + if (!toCheckInput) return LabeledPolynomial(coefs) + + val fixedCoefs = LinkedHashMap, C>(coefs.size) + + for (entry in coefs) { + val key = entry.key.cleanUp() + val value = entry.value + fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value + } + + return LabeledPolynomial(fixedCoefs) +} + +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs, toCheckInput) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs, toCheckInput) +@Suppress("FunctionName") +internal fun > A.LabeledPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : LabeledPolynomial { + if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) + + val fixedCoefs = LinkedHashMap, C>(pairs.size) + + for (entry in pairs) { + val key = entry.first.cleanUp() + val value = entry.second + fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value + } + + return LabeledPolynomial(fixedCoefs) +} + +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > LabeledPolynomialSpace.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs = pairs, toCheckInput = toCheckInput) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > LabeledRationalFunctionSpace.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial = ring.LabeledPolynomial(pairs = pairs, toCheckInput = toCheckInput) +@Suppress("FunctionName") +internal fun > A.LabeledPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : LabeledPolynomial { + if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) + + val fixedCoefs = LinkedHashMap, C>(pairs.size) + + for (entry in pairs) { + val key = entry.first.cleanUp() + val value = entry.second + fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value + } + + return LabeledPolynomial(fixedCoefs) +} + +@Suppress("FunctionName") +public fun > A.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) +@Suppress("FunctionName") +public fun > LabeledPolynomialSpace.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) +@Suppress("FunctionName") +public fun > LabeledRationalFunctionSpace.LabeledPolynomial(coefs: Map, C>) : LabeledPolynomial = LabeledPolynomial(coefs, toCheckInput = true) + +@Suppress("FunctionName") +public fun > A.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > LabeledPolynomialSpace.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > LabeledRationalFunctionSpace.LabeledPolynomial(pairs: Collection, C>>) : LabeledPolynomial = LabeledPolynomial(pairs, toCheckInput = true) + +@Suppress("FunctionName") +public fun > A.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > LabeledPolynomialSpace.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > LabeledRationalFunctionSpace.LabeledPolynomial(vararg pairs: Pair, C>) : LabeledPolynomial = LabeledPolynomial(*pairs, toCheckInput = true) + +//context(A) +//public fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to one)) +//context(LabeledPolynomialSpace) +//public fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to constantOne)) +//context(LabeledRationalFunctionSpace) +//public fun > Symbol.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(mapOf(this to 1u) to constantOne)) + +public fun C.asLabeledPolynomial() : LabeledPolynomial = LabeledPolynomial(mapOf(emptyMap() to this)) + +// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available + +@Suppress("FunctionName") +public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): LabeledRationalFunction = + LabeledRationalFunction( + LabeledPolynomial(numeratorCoefficients, toCheckInput = true), + LabeledPolynomial(denominatorCoefficients, toCheckInput = true) + ) +@Suppress("FunctionName") +public fun > A.LabeledRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): LabeledRationalFunction = + LabeledRationalFunction( + LabeledPolynomial(numeratorCoefficients, toCheckInput = true), + LabeledPolynomial(denominatorCoefficients, toCheckInput = true) + ) +@Suppress("FunctionName") +public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numerator: LabeledPolynomial): LabeledRationalFunction = + LabeledRationalFunction(numerator, polynomialOne) +@Suppress("FunctionName") +public fun > A.LabeledRationalFunction(numerator: LabeledPolynomial): LabeledRationalFunction = + LabeledRationalFunction(numerator, LabeledPolynomial(mapOf(emptyMap() to one), toCheckInput = false)) +@Suppress("FunctionName") +public fun > LabeledRationalFunctionSpace.LabeledRationalFunction(numeratorCoefficients: Map, C>): LabeledRationalFunction = + LabeledRationalFunction( + LabeledPolynomial(numeratorCoefficients, toCheckInput = true), + polynomialOne + ) +@Suppress("FunctionName") +public fun > A.LabeledRationalFunction(numeratorCoefficients: Map, C>): LabeledRationalFunction = + LabeledRationalFunction( + LabeledPolynomial(numeratorCoefficients, toCheckInput = true), + LabeledPolynomial(mapOf(emptyMap() to one), toCheckInput = false) + ) + +//context(A) +//public fun > Symbol.asLabeledRationalFunction() : LabeledRationalFunction = LabeledRationalFunction(asLabeledPolynomial()) +//context(LabeledRationalFunctionSpace) +//public fun > Symbol.asLabeledRationalFunction() : LabeledRationalFunction = LabeledRationalFunction(asLabeledPolynomial()) + +//context(A) +//public fun > C.asLabeledRationalFunction() : LabeledRationalFunction = LabeledRationalFunction(asLabeledPolynomial()) +//context(LabeledRationalFunctionSpace) +//public fun > C.asLabeledRationalFunction() : LabeledRationalFunction = LabeledRationalFunction(asLabeledPolynomial()) \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt new file mode 100644 index 000000000..9498c77ca --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/listConstructors.kt @@ -0,0 +1,60 @@ +/* + * 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 + + +/** + * Returns a [ListPolynomial] instance with given [coefficients]. The collection of coefficients will be reversed if + * [reverse] parameter is true. + */ +@Suppress("FunctionName") +public fun ListPolynomial(coefficients: List, reverse: Boolean = false): ListPolynomial = + ListPolynomial(with(coefficients) { if (reverse) reversed() else this }) + +/** + * Returns a [ListPolynomial] instance with given [coefficients]. The collection of coefficients will be reversed if + * [reverse] parameter is true. + */ +@Suppress("FunctionName") +public fun ListPolynomial(vararg coefficients: C, reverse: Boolean = false): ListPolynomial = + ListPolynomial(with(coefficients) { if (reverse) reversed() else toList() }) + +public fun C.asListPolynomial() : ListPolynomial = ListPolynomial(listOf(this)) + + +// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available + +@Suppress("FunctionName") +public fun ListRationalFunction(numeratorCoefficients: List, denominatorCoefficients: List, reverse: Boolean = false): ListRationalFunction = + ListRationalFunction( + ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), + ListPolynomial( with(denominatorCoefficients) { if (reverse) reversed() else this } ) + ) +@Suppress("FunctionName") +public fun > ListRationalFunctionSpace.ListRationalFunction(numerator: ListPolynomial): ListRationalFunction = + ListRationalFunction(numerator, polynomialOne) +@Suppress("FunctionName") +public fun > A.ListRationalFunction(numerator: ListPolynomial): ListRationalFunction = + ListRationalFunction(numerator, ListPolynomial(listOf(one))) +@Suppress("FunctionName") +public fun > ListRationalFunctionSpace.ListRationalFunction(numeratorCoefficients: List, reverse: Boolean = false): ListRationalFunction = + ListRationalFunction( + ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), + polynomialOne + ) +@Suppress("FunctionName") +public fun > A.ListRationalFunction(numeratorCoefficients: List, reverse: Boolean = false): ListRationalFunction = + ListRationalFunction( + ListPolynomial( with(numeratorCoefficients) { if (reverse) reversed() else this } ), + ListPolynomial(listOf(one)) + ) + +//context(A) +//public fun > C.asListRationalFunction() : ListRationalFunction = ListRationalFunction(asListPolynomial()) +//context(ListRationalFunctionSpace) +//public fun > C.asListRationalFunction() : ListRationalFunction = ListRationalFunction(asListPolynomial()) \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt new file mode 100644 index 000000000..e4b79b0b2 --- /dev/null +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/functions/numberedConstructors.kt @@ -0,0 +1,188 @@ +/* + * 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 + + +/** + * Returns the same degrees' description of the monomial, but without extra zero degrees on the end. + */ +internal fun List.cleanUp() = subList(0, indexOfLast { it != 0U } + 1) + +// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available + +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(coefs, toCheckInput) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(coefs, toCheckInput) +@Suppress("FunctionName") +internal fun > A.NumberedPolynomial(coefs: Map, C>, toCheckInput: Boolean = true) : NumberedPolynomial { + if (!toCheckInput) return NumberedPolynomial(coefs) + + val fixedCoefs = mutableMapOf, C>() + + for (entry in coefs) { + val key = entry.key.cleanUp() + val value = entry.value + fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value + } + + return NumberedPolynomial(fixedCoefs) +} + +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs, toCheckInput) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs, toCheckInput) +@Suppress("FunctionName") +internal fun > A.NumberedPolynomial(pairs: Collection, C>>, toCheckInput: Boolean = true) : NumberedPolynomial { + if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) + + val fixedCoefs = mutableMapOf, C>() + + for (entry in pairs) { + val key = entry.first.cleanUp() + val value = entry.second + fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value + } + + return NumberedPolynomial(fixedCoefs) +} + +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > NumberedPolynomialSpace.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs = pairs, toCheckInput = toCheckInput) +@Suppress("FunctionName", "NOTHING_TO_INLINE") +internal inline fun > NumberedRationalFunctionSpace.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial = ring.NumberedPolynomial(pairs = pairs, toCheckInput = toCheckInput) +@Suppress("FunctionName") +internal fun > A.NumberedPolynomial(vararg pairs: Pair, C>, toCheckInput: Boolean = true) : NumberedPolynomial { + if (!toCheckInput) return NumberedPolynomial(pairs.toMap()) + + val fixedCoefs = mutableMapOf, C>() + + for (entry in pairs) { + val key = entry.first.cleanUp() + val value = entry.second + fixedCoefs[key] = if (key in fixedCoefs) fixedCoefs[key]!! + value else value + } + + return NumberedPolynomial(fixedCoefs) +} + +@Suppress("FunctionName") +public fun > A.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) +@Suppress("FunctionName") +public fun > NumberedPolynomialSpace.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) +@Suppress("FunctionName") +public fun > NumberedRationalFunctionSpace.NumberedPolynomial(coefs: Map, C>) : NumberedPolynomial = NumberedPolynomial(coefs, toCheckInput = true) + +@Suppress("FunctionName") +public fun > A.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > NumberedPolynomialSpace.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > NumberedRationalFunctionSpace.NumberedPolynomial(pairs: Collection, C>>) : NumberedPolynomial = NumberedPolynomial(pairs, toCheckInput = true) + +@Suppress("FunctionName") +public fun > A.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > NumberedPolynomialSpace.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) +@Suppress("FunctionName") +public fun > NumberedRationalFunctionSpace.NumberedPolynomial(vararg pairs: Pair, C>) : NumberedPolynomial = NumberedPolynomial(*pairs, toCheckInput = true) + +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.pow(deg: UInt): Unit = this inPowerOf deg + public infix fun Int.of(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 } + } + public infix fun C.with(block: NumberedPolynomialTermSignatureBuilder.() -> Unit): Unit = this.invoke(block) +} + +@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() + +// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available + +@Suppress("FunctionName") +public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): NumberedRationalFunction = + NumberedRationalFunction( + NumberedPolynomial(numeratorCoefficients, toCheckInput = true), + NumberedPolynomial(denominatorCoefficients, toCheckInput = true) + ) +@Suppress("FunctionName") +public fun > A.NumberedRationalFunction(numeratorCoefficients: Map, C>, denominatorCoefficients: Map, C>): NumberedRationalFunction = + NumberedRationalFunction( + NumberedPolynomial(numeratorCoefficients, toCheckInput = true), + NumberedPolynomial(denominatorCoefficients, toCheckInput = true) + ) +@Suppress("FunctionName") +public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numerator: NumberedPolynomial): NumberedRationalFunction = + NumberedRationalFunction(numerator, polynomialOne) +@Suppress("FunctionName") +public fun > A.NumberedRationalFunction(numerator: NumberedPolynomial): NumberedRationalFunction = + NumberedRationalFunction(numerator, NumberedPolynomial(mapOf(emptyList() to one), toCheckInput = false)) +@Suppress("FunctionName") +public fun > NumberedRationalFunctionSpace.NumberedRationalFunction(numeratorCoefficients: Map, C>): NumberedRationalFunction = + NumberedRationalFunction( + NumberedPolynomial(numeratorCoefficients, toCheckInput = true), + polynomialOne + ) +@Suppress("FunctionName") +public fun > A.NumberedRationalFunction(numeratorCoefficients: Map, C>): NumberedRationalFunction = + NumberedRationalFunction( + NumberedPolynomial(numeratorCoefficients, toCheckInput = true), + NumberedPolynomial(mapOf(emptyList() to one), toCheckInput = false) + ) + +//context(A) +//public fun > C.asNumberedRationalFunction() : NumberedRationalFunction = NumberedRationalFunction(asLabeledPolynomial()) +//context(NumberedRationalFunctionSpace) +//public fun > C.asNumberedRationalFunction() : NumberedRationalFunction = NumberedRationalFunction(asLabeledPolynomial()) \ No newline at end of file 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 d544ca93c..ee85b0f56 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 @@ -9,38 +9,6 @@ import kotlin.math.max // TODO: Docs -//// TODO: Reuse underlying ring extensions -// -//context(NumberedPolynomialSpace) -//@Suppress("NOTHING_TO_INLINE") -//public fun > numberConstant(value: Int): C = ring { number(value) } -// -//context(NumberedPolynomialSpace) -//public fun > multiplyWithPower(base: C, arg: C, pow: UInt): C = ring { multiplyWithPower(base, arg, pow) } - -//context(NumberedPolynomialSpace) -//public fun > number(value: Int): NumberedPolynomial = ring { NumberedPolynomial(mapOf(emptyList() to number(value))) } -// -//context(NumberedPolynomialSpace) -//public fun > multiplyWithPower(base: NumberedPolynomial, arg: NumberedPolynomial, pow: UInt): NumberedPolynomial = -// 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(NumberedPolynomialSpace) -//internal tailrec fun > multiplyWithPowerInternalLogic(base: NumberedPolynomial, arg: NumberedPolynomial, exponent: UInt): NumberedPolynomial = -// 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 [NumberedPolynomialSpace] over a received ring. */ @@ -271,7 +239,6 @@ public inline fun , R> A.numberedPolynomial(block: NumberedPolyno // toCheckInput = false // ) -// TODO: May be apply Horner's method too? /** * Evaluates the value of the given double polynomial for given double argument. */