forked from kscience/kmath
Add utilities for maps. Fix some tests.
This commit is contained in:
parent
4ea29c82c5
commit
579511a5ee
@ -150,12 +150,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
else with(coefficients) {
|
else with(coefficients) {
|
||||||
if (isEmpty()) other.asPolynomial()
|
if (isEmpty()) other.asPolynomial()
|
||||||
else LabeledPolynomialAsIs(
|
else LabeledPolynomialAsIs(
|
||||||
toMutableMap()
|
withPutOrChanged(emptyMap(), other.asConstant()) { it -> it + other }
|
||||||
.apply {
|
|
||||||
val degs = emptyMap<Symbol, UInt>()
|
|
||||||
|
|
||||||
this[degs] = getOrElse(degs) { constantZero } + other
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -168,12 +163,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
else with(coefficients) {
|
else with(coefficients) {
|
||||||
if (isEmpty()) (-other).asPolynomial()
|
if (isEmpty()) (-other).asPolynomial()
|
||||||
else LabeledPolynomialAsIs(
|
else LabeledPolynomialAsIs(
|
||||||
toMutableMap()
|
withPutOrChanged(emptyMap(), (-other).asConstant()) { it -> it - other }
|
||||||
.apply {
|
|
||||||
val degs = emptyMap<Symbol, UInt>()
|
|
||||||
|
|
||||||
this[degs] = getOrElse(degs) { constantZero } - other
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -186,11 +176,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
0 -> zero
|
0 -> zero
|
||||||
1 -> this
|
1 -> this
|
||||||
else -> LabeledPolynomialAsIs(
|
else -> LabeledPolynomialAsIs(
|
||||||
coefficients
|
coefficients.mapValues { (_, value) -> value * other }
|
||||||
.toMutableMap()
|
|
||||||
.apply {
|
|
||||||
for (degs in keys) this[degs] = this[degs]!! * other
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,12 +190,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
else with(other.coefficients) {
|
else with(other.coefficients) {
|
||||||
if (isEmpty()) this@plus.asPolynomial()
|
if (isEmpty()) this@plus.asPolynomial()
|
||||||
else LabeledPolynomialAsIs(
|
else LabeledPolynomialAsIs(
|
||||||
toMutableMap()
|
withPutOrChanged(emptyMap(), this@plus.asConstant()) { it -> this@plus + it }
|
||||||
.apply {
|
|
||||||
val degs = emptyMap<Symbol, UInt>()
|
|
||||||
|
|
||||||
this[degs] = this@plus + getOrElse(degs) { constantZero }
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -218,18 +199,14 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
* The operation is equivalent to subtraction [this] copies of unit polynomial from [other].
|
* The operation is equivalent to subtraction [this] copies of unit polynomial from [other].
|
||||||
*/
|
*/
|
||||||
public override operator fun Int.minus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
public override operator fun Int.minus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||||
if (this == 0) -other
|
when {
|
||||||
else with(other.coefficients) {
|
this == 0 -> -other
|
||||||
if (isEmpty()) this@minus.asPolynomial()
|
other.coefficients.isEmpty() -> this@minus.asPolynomial()
|
||||||
else LabeledPolynomialAsIs(
|
else -> LabeledPolynomialAsIs(
|
||||||
toMutableMap()
|
buildMap(other.coefficients.size + 1) {
|
||||||
.apply {
|
put(emptyMap(), asConstant())
|
||||||
forEach { (key, value) -> if (key.isNotEmpty()) this[key] = -value }
|
other.coefficients.copyMapToBy(this, { _, c -> -c }, { currentC, newC -> currentC - newC })
|
||||||
|
}
|
||||||
val degs = emptyMap<Symbol, UInt>()
|
|
||||||
|
|
||||||
this[degs] = this@minus - getOrElse(degs) { constantZero }
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -242,11 +219,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
0 -> zero
|
0 -> zero
|
||||||
1 -> other
|
1 -> other
|
||||||
else -> LabeledPolynomialAsIs(
|
else -> LabeledPolynomialAsIs(
|
||||||
other.coefficients
|
other.coefficients.mapValues { (_, value) -> this@times * value }
|
||||||
.toMutableMap()
|
|
||||||
.apply {
|
|
||||||
for (degs in keys) this[degs] = this@times * this[degs]!!
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,41 +278,26 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
with(other.coefficients) {
|
with(other.coefficients) {
|
||||||
if (isEmpty()) this@plus.asLabeledPolynomial()
|
if (isEmpty()) this@plus.asLabeledPolynomial()
|
||||||
else LabeledPolynomialAsIs(
|
else LabeledPolynomialAsIs(
|
||||||
toMutableMap()
|
withPutOrChanged(emptyMap(), this@plus) { it -> this@plus + it }
|
||||||
.apply {
|
|
||||||
val degs = emptyMap<Symbol, UInt>()
|
|
||||||
|
|
||||||
this[degs] = this@plus + getOrElse(degs) { constantZero }
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Returns difference between the constant represented as a polynomial and the polynomial.
|
* Returns difference between the constant represented as a polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
override operator fun C.minus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
override operator fun C.minus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||||
with(other.coefficients) {
|
if (other.coefficients.isEmpty()) this@minus.asPolynomial()
|
||||||
if (isEmpty()) this@minus.asLabeledPolynomial()
|
else LabeledPolynomialAsIs(
|
||||||
else LabeledPolynomialAsIs(
|
buildMap(other.coefficients.size + 1) {
|
||||||
toMutableMap()
|
put(emptyMap(), this@minus)
|
||||||
.apply {
|
other.coefficients.copyMapToBy(this, { _, c -> -c }, { currentC, newC -> currentC - newC })
|
||||||
forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c }
|
}
|
||||||
|
)
|
||||||
val degs = emptyMap<Symbol, UInt>()
|
|
||||||
|
|
||||||
this[degs] = this@minus - getOrElse(degs) { constantZero }
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Returns product of the constant represented as a polynomial and the polynomial.
|
* Returns product of the constant represented as a polynomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
override operator fun C.times(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
override operator fun C.times(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||||
LabeledPolynomialAsIs(
|
LabeledPolynomialAsIs(
|
||||||
other.coefficients
|
other.coefficients.mapValues { this@times * it.value }
|
||||||
.toMutableMap()
|
|
||||||
.apply {
|
|
||||||
for (degs in keys) this[degs] = this@times * this[degs]!!
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -349,12 +307,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
with(coefficients) {
|
with(coefficients) {
|
||||||
if (isEmpty()) other.asLabeledPolynomial()
|
if (isEmpty()) other.asLabeledPolynomial()
|
||||||
else LabeledPolynomialAsIs(
|
else LabeledPolynomialAsIs(
|
||||||
toMutableMap()
|
withPutOrChanged(emptyMap(), other) { it -> it + other }
|
||||||
.apply {
|
|
||||||
val degs = emptyMap<Symbol, UInt>()
|
|
||||||
|
|
||||||
this[degs] = getOrElse(degs) { constantZero } + other
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -364,12 +317,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
with(coefficients) {
|
with(coefficients) {
|
||||||
if (isEmpty()) other.asLabeledPolynomial()
|
if (isEmpty()) other.asLabeledPolynomial()
|
||||||
else LabeledPolynomialAsIs(
|
else LabeledPolynomialAsIs(
|
||||||
toMutableMap()
|
withPutOrChanged(emptyMap(), -other) { it -> it - other }
|
||||||
.apply {
|
|
||||||
val degs = emptyMap<Symbol, UInt>()
|
|
||||||
|
|
||||||
this[degs] = getOrElse(degs) { constantZero } - other
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -377,11 +325,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
*/
|
*/
|
||||||
override operator fun LabeledPolynomial<C>.times(other: C): LabeledPolynomial<C> =
|
override operator fun LabeledPolynomial<C>.times(other: C): LabeledPolynomial<C> =
|
||||||
LabeledPolynomialAsIs(
|
LabeledPolynomialAsIs(
|
||||||
coefficients
|
coefficients.mapValues { it.value * other }
|
||||||
.toMutableMap()
|
|
||||||
.apply {
|
|
||||||
for (degs in keys) this[degs] = this[degs]!! * other
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -441,38 +385,27 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
with(other.coefficients) {
|
with(other.coefficients) {
|
||||||
if (isEmpty()) this@plus.asPolynomial()
|
if (isEmpty()) this@plus.asPolynomial()
|
||||||
else LabeledPolynomialAsIs(
|
else LabeledPolynomialAsIs(
|
||||||
toMutableMap()
|
withPutOrChanged(mapOf(this@plus to 1U), constantOne) { it -> constantOne + it }
|
||||||
.apply {
|
|
||||||
val degs = mapOf(this@plus to 1U)
|
|
||||||
|
|
||||||
this[degs] = constantOne + getOrElse(degs) { constantZero }
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Returns difference between the variable represented as a monic monomial and the polynomial.
|
* Returns difference between the variable represented as a monic monomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
public override operator fun Symbol.minus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
public override operator fun Symbol.minus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||||
with(other.coefficients) {
|
if (other.coefficients.isEmpty()) this@minus.asPolynomial()
|
||||||
if (isEmpty()) this@minus.asPolynomial()
|
else LabeledPolynomialAsIs(
|
||||||
else LabeledPolynomialAsIs(
|
buildMap(other.coefficients.size + 1) {
|
||||||
toMutableMap()
|
put(mapOf(this@minus to 1U), constantOne)
|
||||||
.apply {
|
other.coefficients.copyMapToBy(this, { _, c -> -c }) { currentC, newC -> currentC - newC }
|
||||||
val theVariableDegs = mapOf(this@minus to 1U)
|
}
|
||||||
|
)
|
||||||
forEach { (degs, c) -> if(degs != theVariableDegs) this[degs] = -c }
|
|
||||||
|
|
||||||
this[theVariableDegs] = constantOne - getOrElse(theVariableDegs) { constantZero }
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Returns product of the variable represented as a monic monomial and the polynomial.
|
* Returns product of the variable represented as a monic monomial and the polynomial.
|
||||||
*/
|
*/
|
||||||
public override operator fun Symbol.times(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
public override operator fun Symbol.times(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||||
LabeledPolynomialAsIs(
|
LabeledPolynomialAsIs(
|
||||||
other.coefficients
|
other.coefficients
|
||||||
.mapKeys { (degs, _) -> degs.toMutableMap().also{ it[this] = if (this in it) it[this]!! + 1U else 1U } }
|
.mapKeys { (degs, _) -> degs.withPutOrChanged(this, 1u) { it -> it + 1u } }
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -482,12 +415,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
with(coefficients) {
|
with(coefficients) {
|
||||||
if (isEmpty()) other.asPolynomial()
|
if (isEmpty()) other.asPolynomial()
|
||||||
else LabeledPolynomialAsIs(
|
else LabeledPolynomialAsIs(
|
||||||
toMutableMap()
|
withPutOrChanged(mapOf(other to 1U), constantOne) { it -> it + constantOne }
|
||||||
.apply {
|
|
||||||
val degs = mapOf(other to 1U)
|
|
||||||
|
|
||||||
this[degs] = constantOne + getOrElse(degs) { constantZero }
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -497,12 +425,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
with(coefficients) {
|
with(coefficients) {
|
||||||
if (isEmpty()) other.asPolynomial()
|
if (isEmpty()) other.asPolynomial()
|
||||||
else LabeledPolynomialAsIs(
|
else LabeledPolynomialAsIs(
|
||||||
toMutableMap()
|
withPutOrChanged(mapOf(other to 1U), -constantOne) { it -> it - constantOne }
|
||||||
.apply {
|
|
||||||
val degs = mapOf(other to 1U)
|
|
||||||
|
|
||||||
this[degs] = getOrElse(degs) { constantZero } - constantOne
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -511,7 +434,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
public override operator fun LabeledPolynomial<C>.times(other: Symbol): LabeledPolynomial<C> =
|
public override operator fun LabeledPolynomial<C>.times(other: Symbol): LabeledPolynomial<C> =
|
||||||
LabeledPolynomialAsIs(
|
LabeledPolynomialAsIs(
|
||||||
coefficients
|
coefficients
|
||||||
.mapKeys { (degs, _) -> degs.toMutableMap().also{ it[other] = if (other in it) it[other]!! + 1U else 1U } }
|
.mapKeys { (degs, _) -> degs.withPutOrChanged(other, 1u) { it -> it + 1u } }
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -526,10 +449,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
*/
|
*/
|
||||||
override operator fun LabeledPolynomial<C>.plus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
override operator fun LabeledPolynomial<C>.plus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||||
LabeledPolynomialAsIs(
|
LabeledPolynomialAsIs(
|
||||||
buildMap(coefficients.size + other.coefficients.size) {
|
mergeBy(coefficients, other.coefficients) { c1, c2 -> c1 + c2 }
|
||||||
coefficients.mapValuesTo(this) { it.value }
|
|
||||||
other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value }
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
* Returns difference of the polynomials.
|
* Returns difference of the polynomials.
|
||||||
@ -537,8 +457,8 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
override operator fun LabeledPolynomial<C>.minus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
override operator fun LabeledPolynomial<C>.minus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
|
||||||
LabeledPolynomialAsIs(
|
LabeledPolynomialAsIs(
|
||||||
buildMap(coefficients.size + other.coefficients.size) {
|
buildMap(coefficients.size + other.coefficients.size) {
|
||||||
coefficients.mapValuesTo(this) { it.value }
|
coefficients.copyTo(this)
|
||||||
other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value }
|
other.coefficients.copyMapToBy(this, { _, c -> -c }, { currentC, newC -> currentC - newC })
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
@ -548,10 +468,9 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
LabeledPolynomialAsIs(
|
LabeledPolynomialAsIs(
|
||||||
buildMap(coefficients.size * other.coefficients.size) {
|
buildMap(coefficients.size * other.coefficients.size) {
|
||||||
for ((degs1, c1) in coefficients) for ((degs2, c2) in other.coefficients) {
|
for ((degs1, c1) in coefficients) for ((degs2, c2) in other.coefficients) {
|
||||||
val degs = degs1.toMutableMap()
|
val degs = mergeBy(degs1, degs2) { deg1, deg2 -> deg1 + deg2 }
|
||||||
degs2.mapValuesTo(degs) { (variable, deg) -> degs.getOrElse(variable) { 0u } + deg }
|
|
||||||
val c = c1 * c2
|
val c = c1 * c2
|
||||||
this[degs] = if (degs in this) this[degs]!! + c else c
|
this.putOrChange(degs, c) { it -> it + c }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -581,10 +500,8 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
|||||||
public override val LabeledPolynomial<C>.degrees: Map<Symbol, UInt>
|
public override val LabeledPolynomial<C>.degrees: Map<Symbol, UInt>
|
||||||
get() =
|
get() =
|
||||||
buildMap {
|
buildMap {
|
||||||
coefficients.entries.forEach { (degs, _) ->
|
coefficients.keys.forEach { degs ->
|
||||||
degs.mapValuesTo(this) { (variable, deg) ->
|
degs.copyToBy(this, ::max)
|
||||||
max(getOrElse(variable) { 0u }, deg)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -109,11 +109,7 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
|
|||||||
0 -> zero
|
0 -> zero
|
||||||
1 -> this
|
1 -> this
|
||||||
else -> ListPolynomial(
|
else -> ListPolynomial(
|
||||||
coefficients
|
coefficients.map { it * other }
|
||||||
.toMutableList()
|
|
||||||
.apply {
|
|
||||||
for (deg in indices) this[deg] = this[deg] * other
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,11 +163,7 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
|
|||||||
0 -> zero
|
0 -> zero
|
||||||
1 -> other
|
1 -> other
|
||||||
else -> ListPolynomial(
|
else -> ListPolynomial(
|
||||||
other.coefficients
|
other.coefficients.map { this@times * it }
|
||||||
.toMutableList()
|
|
||||||
.apply {
|
|
||||||
for (deg in indices) this[deg] = this@times * this[deg]
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,11 +206,7 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
|
|||||||
*/
|
*/
|
||||||
public override operator fun C.times(other: ListPolynomial<C>): ListPolynomial<C> =
|
public override operator fun C.times(other: ListPolynomial<C>): ListPolynomial<C> =
|
||||||
ListPolynomial(
|
ListPolynomial(
|
||||||
other.coefficients
|
other.coefficients.map { this@times * it }
|
||||||
.toMutableList()
|
|
||||||
.apply {
|
|
||||||
for (deg in indices) this[deg] = this@times * this[deg]
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -258,11 +246,7 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
|
|||||||
*/
|
*/
|
||||||
public override operator fun ListPolynomial<C>.times(other: C): ListPolynomial<C> =
|
public override operator fun ListPolynomial<C>.times(other: C): ListPolynomial<C> =
|
||||||
ListPolynomial(
|
ListPolynomial(
|
||||||
coefficients
|
coefficients.map { it * other }
|
||||||
.toMutableList()
|
|
||||||
.apply {
|
|
||||||
for (deg in indices) this[deg] = this[deg] * other
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -71,13 +71,7 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
if (other == 0) this
|
if (other == 0) this
|
||||||
else
|
else
|
||||||
NumberedPolynomialAsIs(
|
NumberedPolynomialAsIs(
|
||||||
coefficients
|
coefficients.withPutOrChanged(emptyList(), other.asConstant()) { it -> it + other }
|
||||||
.toMutableMap()
|
|
||||||
.apply {
|
|
||||||
val degs = emptyList<UInt>()
|
|
||||||
|
|
||||||
this[degs] = getOrElse(degs) { constantZero } + other
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
* Returns difference between the polynomial and the integer represented as a polynomial.
|
* Returns difference between the polynomial and the integer represented as a polynomial.
|
||||||
@ -88,13 +82,7 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
if (other == 0) this
|
if (other == 0) this
|
||||||
else
|
else
|
||||||
NumberedPolynomialAsIs(
|
NumberedPolynomialAsIs(
|
||||||
coefficients
|
coefficients.withPutOrChanged(emptyList(), (-other).asConstant()) { it -> it - other }
|
||||||
.toMutableMap()
|
|
||||||
.apply {
|
|
||||||
val degs = emptyList<UInt>()
|
|
||||||
|
|
||||||
this[degs] = getOrElse(degs) { constantZero } - other
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
* Returns product of the polynomial and the integer represented as a polynomial.
|
* Returns product of the polynomial and the integer represented as a polynomial.
|
||||||
@ -106,11 +94,7 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
0 -> zero
|
0 -> zero
|
||||||
1 -> this
|
1 -> this
|
||||||
else -> NumberedPolynomialAsIs(
|
else -> NumberedPolynomialAsIs(
|
||||||
coefficients
|
coefficients.mapValues { it.value * other }
|
||||||
.toMutableMap()
|
|
||||||
.apply {
|
|
||||||
for (degs in keys) this[degs] = this[degs]!! * other
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,13 +107,7 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
if (this == 0) other
|
if (this == 0) other
|
||||||
else
|
else
|
||||||
NumberedPolynomialAsIs(
|
NumberedPolynomialAsIs(
|
||||||
other.coefficients
|
other.coefficients.withPutOrChanged(emptyList(), this@plus.asConstant()) { it -> this@plus + it }
|
||||||
.toMutableMap()
|
|
||||||
.apply {
|
|
||||||
val degs = emptyList<UInt>()
|
|
||||||
|
|
||||||
this[degs] = this@plus + getOrElse(degs) { constantZero }
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
* Returns difference between the integer represented as a polynomial and the polynomial.
|
* Returns difference between the integer represented as a polynomial and the polynomial.
|
||||||
@ -162,11 +140,7 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
0 -> zero
|
0 -> zero
|
||||||
1 -> other
|
1 -> other
|
||||||
else -> NumberedPolynomialAsIs(
|
else -> NumberedPolynomialAsIs(
|
||||||
other.coefficients
|
other.coefficients.mapValues { this@times * it.value }
|
||||||
.toMutableMap()
|
|
||||||
.apply {
|
|
||||||
for (degs in keys) this[degs] = this@times * this[degs]!!
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,12 +151,7 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
with(other.coefficients) {
|
with(other.coefficients) {
|
||||||
if (isEmpty()) NumberedPolynomialAsIs(mapOf(emptyList<UInt>() to this@plus))
|
if (isEmpty()) NumberedPolynomialAsIs(mapOf(emptyList<UInt>() to this@plus))
|
||||||
else NumberedPolynomialAsIs(
|
else NumberedPolynomialAsIs(
|
||||||
toMutableMap()
|
withPutOrChanged(emptyList(), this@plus) { it -> this@plus + it }
|
||||||
.apply {
|
|
||||||
val degs = emptyList<UInt>()
|
|
||||||
|
|
||||||
this[degs] = this@plus + getOrElse(degs) { constantZero }
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -207,11 +176,7 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
*/
|
*/
|
||||||
override operator fun C.times(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
override operator fun C.times(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
||||||
NumberedPolynomialAsIs(
|
NumberedPolynomialAsIs(
|
||||||
other.coefficients
|
other.coefficients.mapValues { this@times * it.value }
|
||||||
.toMutableMap()
|
|
||||||
.apply {
|
|
||||||
for (degs in keys) this[degs] = this@times * this[degs]!!
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -221,12 +186,7 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
with(coefficients) {
|
with(coefficients) {
|
||||||
if (isEmpty()) NumberedPolynomialAsIs(mapOf(emptyList<UInt>() to other))
|
if (isEmpty()) NumberedPolynomialAsIs(mapOf(emptyList<UInt>() to other))
|
||||||
else NumberedPolynomialAsIs(
|
else NumberedPolynomialAsIs(
|
||||||
toMutableMap()
|
withPutOrChanged(emptyList(), other) { it -> it + other }
|
||||||
.apply {
|
|
||||||
val degs = emptyList<UInt>()
|
|
||||||
|
|
||||||
this[degs] = getOrElse(degs) { constantZero } + other
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -236,12 +196,7 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
with(coefficients) {
|
with(coefficients) {
|
||||||
if (isEmpty()) NumberedPolynomialAsIs(mapOf(emptyList<UInt>() to other))
|
if (isEmpty()) NumberedPolynomialAsIs(mapOf(emptyList<UInt>() to other))
|
||||||
else NumberedPolynomialAsIs(
|
else NumberedPolynomialAsIs(
|
||||||
toMutableMap()
|
withPutOrChanged(emptyList(), -other) { it -> it - other }
|
||||||
.apply {
|
|
||||||
val degs = emptyList<UInt>()
|
|
||||||
|
|
||||||
this[degs] = getOrElse(degs) { constantZero } - other
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -249,11 +204,7 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
*/
|
*/
|
||||||
override operator fun NumberedPolynomial<C>.times(other: C): NumberedPolynomial<C> =
|
override operator fun NumberedPolynomial<C>.times(other: C): NumberedPolynomial<C> =
|
||||||
NumberedPolynomialAsIs(
|
NumberedPolynomialAsIs(
|
||||||
coefficients
|
coefficients.mapValues { it.value * other }
|
||||||
.toMutableMap()
|
|
||||||
.apply {
|
|
||||||
for (degs in keys) this[degs] = this[degs]!! * other
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -274,10 +225,7 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
*/
|
*/
|
||||||
override operator fun NumberedPolynomial<C>.plus(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
override operator fun NumberedPolynomial<C>.plus(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
||||||
NumberedPolynomialAsIs(
|
NumberedPolynomialAsIs(
|
||||||
buildMap(coefficients.size + other.coefficients.size) {
|
mergeBy(coefficients, other.coefficients) { c1, c2 -> c1 + c2 }
|
||||||
coefficients.mapValuesTo(this) { it.value }
|
|
||||||
other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! + value else value }
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
* Returns difference of the polynomials.
|
* Returns difference of the polynomials.
|
||||||
@ -285,8 +233,8 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
override operator fun NumberedPolynomial<C>.minus(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
override operator fun NumberedPolynomial<C>.minus(other: NumberedPolynomial<C>): NumberedPolynomial<C> =
|
||||||
NumberedPolynomialAsIs(
|
NumberedPolynomialAsIs(
|
||||||
buildMap(coefficients.size + other.coefficients.size) {
|
buildMap(coefficients.size + other.coefficients.size) {
|
||||||
coefficients.mapValuesTo(this) { it.value }
|
coefficients.copyTo(this)
|
||||||
other.coefficients.mapValuesTo(this) { (key, value) -> if (key in this) this[key]!! - value else -value }
|
other.coefficients.copyMapToBy(this, { _, c -> -c }, { currentC, newC -> currentC - newC })
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
@ -300,7 +248,7 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
(0..max(degs1.lastIndex, degs2.lastIndex))
|
(0..max(degs1.lastIndex, degs2.lastIndex))
|
||||||
.map { degs1.getOrElse(it) { 0U } + degs2.getOrElse(it) { 0U } }
|
.map { degs1.getOrElse(it) { 0U } + degs2.getOrElse(it) { 0U } }
|
||||||
val c = c1 * c2
|
val c = c1 * c2
|
||||||
this[degs] = if (degs in this) this[degs]!! + c else c
|
putOrChange(degs, c) { it -> it + c }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -0,0 +1,500 @@
|
|||||||
|
/*
|
||||||
|
* 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 kotlin.contracts.InvocationKind.*
|
||||||
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the [transformation][transform] to the value corresponding to the given [key] or null instead if it's not
|
||||||
|
* present.
|
||||||
|
*
|
||||||
|
* @param key key to check.
|
||||||
|
* @param transform transformation to apply.
|
||||||
|
* @return result of the transformation
|
||||||
|
*/
|
||||||
|
internal inline fun <K, V> MutableMap<in K, V>.applyToKey(key: K, transform: (currentValue: V?) -> V): V {
|
||||||
|
contract {
|
||||||
|
callsInPlace(transform, EXACTLY_ONCE)
|
||||||
|
}
|
||||||
|
return transform(get(key)).also { this[key] = it }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Depending on presence of value corresponding to the given [key] either puts new value calculated by [valueOnPut] or
|
||||||
|
* changes the present value with [transformOnChange].
|
||||||
|
*
|
||||||
|
* @param key key to check.
|
||||||
|
* @param valueOnPut lazily calculated value to put in case of absence of the [key].
|
||||||
|
* @param transformOnChange transform to apply to current value corresponding to the [key] in case of its presence. Uses
|
||||||
|
* current value as a parameter.
|
||||||
|
* @return result value corresponding to the [key].
|
||||||
|
*/
|
||||||
|
internal inline fun <K, V> MutableMap<K, V>.putOrChange(key: K, valueOnPut: () -> V, transformOnChange: (currentValue: V) -> V): V {
|
||||||
|
contract {
|
||||||
|
callsInPlace(valueOnPut, AT_MOST_ONCE)
|
||||||
|
callsInPlace(transformOnChange, AT_MOST_ONCE)
|
||||||
|
}
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
return (if (key !in this) valueOnPut() else transformOnChange(get(key) as V)).also { this[key] = it }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Depending on presence of value corresponding to the given [key] either puts new value [valueOnPut] or
|
||||||
|
* changes the present value with [transformOnChange].
|
||||||
|
*
|
||||||
|
* @param key key to check.
|
||||||
|
* @param valueOnPut value to put in case of absence of the [key].
|
||||||
|
* @param transformOnChange transform to apply to current value corresponding to the [key] in case of its presence. Uses
|
||||||
|
* current value as a parameter.
|
||||||
|
* @return result value corresponding to the [key].
|
||||||
|
*/
|
||||||
|
internal inline fun <K, V> MutableMap<K, V>.putOrChange(key: K, valueOnPut: V, transformOnChange: (currentValue: V) -> V): V {
|
||||||
|
contract {
|
||||||
|
callsInPlace(transformOnChange, AT_MOST_ONCE)
|
||||||
|
}
|
||||||
|
return putOrChange<K, V>(key, { valueOnPut }, transformOnChange)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Depending on presence of value corresponding to the given [key] either puts new value [valueOnPut] or
|
||||||
|
* changes the present value with [transformOnChange].
|
||||||
|
*
|
||||||
|
* @param key key to check.
|
||||||
|
* @param valueOnPut value to put in case of absence of the [key].
|
||||||
|
* @param transformOnChange transform to apply to current value corresponding to the [key] in case of its presence. Uses
|
||||||
|
* current value and new value as parameters.
|
||||||
|
* @return result value corresponding to the [key].
|
||||||
|
*/
|
||||||
|
internal inline fun <K, V> MutableMap<K, V>.putOrChange(key: K, valueOnPut: V, transformOnChange: (currentValue: V, newValue: V) -> V): V {
|
||||||
|
contract {
|
||||||
|
callsInPlace(transformOnChange, AT_MOST_ONCE)
|
||||||
|
}
|
||||||
|
return putOrChange<K, V>(key, { valueOnPut }, { transformOnChange(it, valueOnPut) })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Depending on presence of value corresponding to the given [key] either puts new value [valueOnPut] or
|
||||||
|
* changes the present value with [transformOnChange].
|
||||||
|
*
|
||||||
|
* @param key key to check.
|
||||||
|
* @param valueOnPut value to put in case of absence of the [key].
|
||||||
|
* @param transformOnChange transform to apply to current value corresponding to the [key] in case of its presence. Uses
|
||||||
|
* the [key], current value, and new value as parameters.
|
||||||
|
* @return result value corresponding to the [key].
|
||||||
|
*/
|
||||||
|
internal inline fun <K, V> MutableMap<K, V>.putOrChange(key: K, valueOnPut: V, transformOnChange: (key: K, currentValue: V, newValue: V) -> V): V {
|
||||||
|
contract {
|
||||||
|
callsInPlace(transformOnChange, AT_MOST_ONCE)
|
||||||
|
}
|
||||||
|
return putOrChange<K, V>(key, { valueOnPut }, { transformOnChange(key, it, valueOnPut) })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates copy of [the map][this] and applies the [transformation][transform] to the value corresponding to the given
|
||||||
|
* [key] in the copy or null instead if it's not present.
|
||||||
|
*
|
||||||
|
* @param key key to check.
|
||||||
|
* @param transform transformation to apply.
|
||||||
|
* @return the copy of [the map][this].
|
||||||
|
*/
|
||||||
|
internal inline fun <K, V> Map<in K, V>.withAppliedToKey(key: K, transform: (currentValue: V?) -> V): Map<K, V> {
|
||||||
|
contract {
|
||||||
|
callsInPlace(transform, EXACTLY_ONCE)
|
||||||
|
}
|
||||||
|
return buildMap(size) {
|
||||||
|
putAll(this)
|
||||||
|
applyToKey(key, transform)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates copy of [the map][this] and depending on presence of value corresponding to the given [key] either puts new
|
||||||
|
* value calculated by [valueOnPut] or changes the present value with [transformOnChange].
|
||||||
|
*
|
||||||
|
* @param key key to check.
|
||||||
|
* @param valueOnPut lazily calculated value to put in case of absence of the [key].
|
||||||
|
* @param transformOnChange transform to apply to current value corresponding to the [key] in case of its presence. Uses
|
||||||
|
* current value as a parameter.
|
||||||
|
* @return the copy of [the map][this].
|
||||||
|
*/
|
||||||
|
internal inline fun <K, V> Map<K, V>.withPutOrChanged(key: K, valueOnPut: () -> V, transformOnChange: (currentValue: V) -> V): Map<K, V> {
|
||||||
|
contract {
|
||||||
|
callsInPlace(valueOnPut, AT_MOST_ONCE)
|
||||||
|
callsInPlace(transformOnChange, AT_MOST_ONCE)
|
||||||
|
}
|
||||||
|
return buildMap(size + 1) {
|
||||||
|
putAll(this@withPutOrChanged)
|
||||||
|
putOrChange(key, valueOnPut, transformOnChange)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates copy of [the map][this] and depending on presence of value corresponding to the given [key] either puts new
|
||||||
|
* value [valueOnPut] or changes the present value with [transformOnChange].
|
||||||
|
*
|
||||||
|
* @param key key to check.
|
||||||
|
* @param valueOnPut value to put in case of absence of the [key].
|
||||||
|
* @param transformOnChange transform to apply to current value corresponding to the [key] in case of its presence. Uses
|
||||||
|
* current value as a parameter.
|
||||||
|
* @return the copy of [the map][this].
|
||||||
|
*/
|
||||||
|
internal inline fun <K, V> Map<K, V>.withPutOrChanged(key: K, valueOnPut: V, transformOnChange: (currentValue: V) -> V): Map<K, V> {
|
||||||
|
contract {
|
||||||
|
callsInPlace(transformOnChange, AT_MOST_ONCE)
|
||||||
|
}
|
||||||
|
return withPutOrChanged<K, V>(key, { valueOnPut }, transformOnChange)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates copy of [the map][this] and depending on presence of value corresponding to the given [key] either puts new
|
||||||
|
* value [valueOnPut] or changes the present value with [transformOnChange].
|
||||||
|
*
|
||||||
|
* @param key key to check.
|
||||||
|
* @param valueOnPut value to put in case of absence of the [key].
|
||||||
|
* @param transformOnChange transform to apply to current value corresponding to the [key] in case of its presence. Uses
|
||||||
|
* current value and new value as parameters.
|
||||||
|
* @return the copy of [the map][this].
|
||||||
|
*/
|
||||||
|
internal inline fun <K, V> Map<K, V>.withPutOrChanged(key: K, valueOnPut: V, transformOnChange: (currentValue: V, newValue: V) -> V): Map<K, V> {
|
||||||
|
contract {
|
||||||
|
callsInPlace(transformOnChange, AT_MOST_ONCE)
|
||||||
|
}
|
||||||
|
return withPutOrChanged<K, V>(key, { valueOnPut }, { transformOnChange(it, valueOnPut) })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates copy of [the map][this] and depending on presence of value corresponding to the given [key] either puts new
|
||||||
|
* value [valueOnPut] or changes the present value with [transformOnChange].
|
||||||
|
*
|
||||||
|
* @param key key to check.
|
||||||
|
* @param valueOnPut value to put in case of absence of the [key].
|
||||||
|
* @param transformOnChange transform to apply to current value corresponding to the [key] in case of its presence. Uses
|
||||||
|
* the [key], current value, and new value as parameters.
|
||||||
|
* @return the copy of [the map][this].
|
||||||
|
*/
|
||||||
|
internal inline fun <K, V> Map<K, V>.withPutOrChanged(key: K, valueOnPut: V, transformOnChange: (key: K, currentValue: V, newValue: V) -> V): Map<K, V> {
|
||||||
|
contract {
|
||||||
|
callsInPlace(transformOnChange, AT_MOST_ONCE)
|
||||||
|
}
|
||||||
|
return withPutOrChanged<K, V>(key, { valueOnPut }, { transformOnChange(key, it, valueOnPut) })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies entries of [this map][this] to the [destination] map overriding present ones if needed.
|
||||||
|
*
|
||||||
|
* @receiver map to be copied.
|
||||||
|
* @param destination map to receive copies.
|
||||||
|
* @return the [destination].
|
||||||
|
*/
|
||||||
|
internal fun <K, V, D: MutableMap<K, V>> Map<K, V>.copyTo(destination: D): D {
|
||||||
|
for ((key, value) in this) {
|
||||||
|
destination[key] = value
|
||||||
|
}
|
||||||
|
return destination
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies entries of [this map][this] to the [destination] map merging present entries with new ones using [resolve]
|
||||||
|
* lambda.
|
||||||
|
*
|
||||||
|
* @receiver map to be copied.
|
||||||
|
* @param destination map to receive copies.
|
||||||
|
* @param resolve lambda function that resolves overriding. It takes a key, current value corresponding to the key, and
|
||||||
|
* a new one and returns value to associate to the key.
|
||||||
|
* @return the [destination].
|
||||||
|
*/
|
||||||
|
internal inline fun <K, V: W, W, D: MutableMap<K, W>> Map<out K, V>.copyToBy(destination: D, resolve: (key: K, currentValue: W, newValue: V) -> W): D {
|
||||||
|
for ((key, value) in this) {
|
||||||
|
destination.putOrChange(key, value) { it -> resolve(key, it, value) }
|
||||||
|
}
|
||||||
|
return destination
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies entries of [this map][this] to the [destination] map merging present entries with new ones using [resolve]
|
||||||
|
* lambda.
|
||||||
|
*
|
||||||
|
* @receiver map to be copied.
|
||||||
|
* @param destination map to receive copies.
|
||||||
|
* @param resolve lambda function that resolves overriding. It takes current value corresponding to some key, and
|
||||||
|
* a new one and returns value to associate to the key.
|
||||||
|
* @return the [destination].
|
||||||
|
*/
|
||||||
|
internal inline fun <K, V: W, W, D: MutableMap<K, W>> Map<out K, V>.copyToBy(destination: D, resolve: (currentValue: W, newValue: V) -> W): D =
|
||||||
|
copyToBy(destination) { _, currentValue, newValue -> resolve(currentValue, newValue) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms values of entries of [this map][this] with [the given transformation][transform] and copies resulting
|
||||||
|
* entries to the [destination] map overriding present ones if needed. Is equivalent to
|
||||||
|
* ```kotlin
|
||||||
|
* this.mapValues(transform).copyTo(destination)
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @receiver map to be transformed and copied.
|
||||||
|
* @param destination map to receive copies.
|
||||||
|
* @param transform generates value of transformed entry using initial entry as an argument. Key of transformed entry is
|
||||||
|
* the same as initial entry.
|
||||||
|
* @return the [destination].
|
||||||
|
*/
|
||||||
|
internal inline fun <K, V, W, D: MutableMap<K, W>> Map<out K, V>.copyMapTo(destination: D, transform: (Map.Entry<K, V>) -> W): D {
|
||||||
|
for (entry in this) {
|
||||||
|
destination[entry.key] = transform(entry)
|
||||||
|
}
|
||||||
|
return destination
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms values of entries of [this map][this] with [the given transformation][transform] and copies resulting
|
||||||
|
* entries to the [destination] map overriding present ones if needed. Is equivalent to
|
||||||
|
* ```kotlin
|
||||||
|
* this.mapValues(transform).copyTo(destination)
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @receiver map to be transformed and copied.
|
||||||
|
* @param destination map to receive copies.
|
||||||
|
* @param transform generates value of transformed entry using initial entry as an argument. Key of transformed entry is
|
||||||
|
* the same as initial entry.
|
||||||
|
* @return the [destination].
|
||||||
|
*/
|
||||||
|
internal inline fun <K, V, W, D: MutableMap<K, W>> Map<out K, V>.copyMapTo(destination: D, transform: (key: K, value: V) -> W): D =
|
||||||
|
copyMapTo(destination) { (key, value) -> transform(key, value) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms values of entries of [this map][this] with [the given transformation][transform] and copies resulting
|
||||||
|
* entries to the [destination] map merging present entries with new ones using [resolve] lambda. Is equivalent to
|
||||||
|
* ```kotlin
|
||||||
|
* this.mapValues(transform).copyToBy(destination, resolve)
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @receiver map to be transformed and copied.
|
||||||
|
* @param destination map to receive copies.
|
||||||
|
* @param transform generates value of transformed entry using initial entry as an argument. Key of transformed entry is
|
||||||
|
* the same as initial entry.
|
||||||
|
* @param resolve lambda function that resolves overriding. It takes a key, current value corresponding to the key, and
|
||||||
|
* a new one and returns value to associate to the key.
|
||||||
|
* @return the [destination].
|
||||||
|
*/
|
||||||
|
internal inline fun <K, V, W, D: MutableMap<K, W>> Map<out K, V>.copyMapToBy(destination: D, transform: (Map.Entry<K, V>) -> W, resolve: (key: K, currentValue: W, newValue: V) -> W): D {
|
||||||
|
for (entry in this) {
|
||||||
|
val (key, value) = entry
|
||||||
|
destination.putOrChange(key, transform(entry)) { it -> resolve(key, it, value) }
|
||||||
|
}
|
||||||
|
return destination
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms values of entries of [this map][this] with [the given transformation][transform] and copies resulting
|
||||||
|
* entries to the [destination] map merging present entries with new ones using [resolve] lambda. Is equivalent to
|
||||||
|
* ```kotlin
|
||||||
|
* this.mapValues(transform).copyToBy(destination, resolve)
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @receiver map to be transformed and copied.
|
||||||
|
* @param destination map to receive copies.
|
||||||
|
* @param transform generates value of transformed entry using initial entry as an argument. Key of transformed entry is
|
||||||
|
* the same as initial entry.
|
||||||
|
* @param resolve lambda function that resolves overriding. It takes a key, current value corresponding to the key, and
|
||||||
|
* a new one and returns value to associate to the key.
|
||||||
|
* @return the [destination].
|
||||||
|
*/
|
||||||
|
internal inline fun <K, V, W, D: MutableMap<K, W>> Map<out K, V>.copyMapToBy(destination: D, transform: (key: K, value: V) -> W, resolve: (key: K, currentValue: W, newValue: V) -> W): D =
|
||||||
|
copyMapToBy(destination, { (key, value) -> transform(key, value) }, resolve)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms values of entries of [this map][this] with [the given transformation][transform] and copies resulting
|
||||||
|
* entries to the [destination] map merging present entries with new ones using [resolve] lambda. Is equivalent to
|
||||||
|
* ```kotlin
|
||||||
|
* this.mapValues(transform).copyToBy(destination, resolve)
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @receiver map to be transformed and copied.
|
||||||
|
* @param destination map to receive copies.
|
||||||
|
* @param transform generates value of transformed entry using initial entry as an argument. Key of transformed entry is
|
||||||
|
* the same as initial entry.
|
||||||
|
* @param resolve lambda function that resolves overriding. It takes current value corresponding to some key, and
|
||||||
|
* a new one and returns value to associate to the key.
|
||||||
|
* @return the [destination].
|
||||||
|
*/
|
||||||
|
internal inline fun <K, V, W, D: MutableMap<K, W>> Map<out K, V>.copyMapToBy(destination: D, transform: (Map.Entry<K, V>) -> W, resolve: (currentValue: W, newValue: V) -> W): D =
|
||||||
|
copyMapToBy(destination, transform, { _, currentValue, newValue -> resolve(currentValue, newValue) })
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms values of entries of [this map][this] with [the given transformation][transform] and copies resulting
|
||||||
|
* entries to the [destination] map merging present entries with new ones using [resolve] lambda. Is equivalent to
|
||||||
|
* ```kotlin
|
||||||
|
* this.mapValues(transform).copyToBy(destination, resolve)
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @receiver map to be transformed and copied.
|
||||||
|
* @param destination map to receive copies.
|
||||||
|
* @param transform generates value of transformed entry using initial entry as an argument. Key of transformed entry is
|
||||||
|
* the same as initial entry.
|
||||||
|
* @param resolve lambda function that resolves overriding. It takes current value corresponding to some key, and
|
||||||
|
* a new one and returns value to associate to the key.
|
||||||
|
* @return the [destination].
|
||||||
|
*/
|
||||||
|
internal inline fun <K, V, W, D: MutableMap<K, W>> Map<out K, V>.copyMapToBy(destination: D, transform: (key: K, value: V) -> W, resolve: (currentValue: W, newValue: V) -> W): D =
|
||||||
|
copyMapToBy(destination, { (key, value) -> transform(key, value) }, { _, currentValue, newValue -> resolve(currentValue, newValue) })
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal fun <K, V, D: MutableMap<K, V>> mergeTo(map1: Map<out K, V>, map2: Map<out K, V>, destination: D): D {
|
||||||
|
for ((key, value) in map1) {
|
||||||
|
destination.put(key, value)
|
||||||
|
}
|
||||||
|
for ((key, value) in map2) {
|
||||||
|
destination.put(key, value)
|
||||||
|
}
|
||||||
|
return destination
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <K, V1: W, V2: W, W, D: MutableMap<K, W>> mergeToBy(map1: Map<out K, V1>, map2: Map<out K, V2>, destination: D, resolve: (key: K, value1: V1, value2: V2) -> W): D {
|
||||||
|
for (key in map2.keys) {
|
||||||
|
destination.remove(key)
|
||||||
|
}
|
||||||
|
for ((key, value) in map1) {
|
||||||
|
destination.put(key, value)
|
||||||
|
}
|
||||||
|
for ((key, value) in map2) {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
destination.putOrChange(key, value) { it -> resolve(key, it as V1, value) }
|
||||||
|
}
|
||||||
|
return destination
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <K, V1: W, V2: W, W, D: MutableMap<K, W>> mergeToBy(map1: Map<K, V1>, map2: Map<K, V2>, destination: D, resolve: (value1: V1, value2: V2) -> W): D =
|
||||||
|
mergeToBy(map1, map2, destination) { _, value1, value2 -> resolve(value1, value2) }
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal fun <K, V1: W, V2: W, W> merge(map1: Map<K, V1>, map2: Map<K, V2>): Map<K, W> {
|
||||||
|
val result = LinkedHashMap<K, W>(map1.size + map2.size)
|
||||||
|
return mergeTo(map1, map2, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <K, V1: W, V2: W, W> mergeBy(map1: Map<K, V1>, map2: Map<K, V2>, transform: (key: K, value1: V1, value2: V2) -> W): Map<K, W> {
|
||||||
|
val result = LinkedHashMap<K, W>(map1.size + map2.size)
|
||||||
|
return mergeToBy(map1, map2, result, transform)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <K, V1: W, V2: W, W> mergeBy(map1: Map<K, V1>, map2: Map<K, V2>, transform: (value1: V1, value2: V2) -> W): Map<K, W> =
|
||||||
|
mergeBy(map1, map2) { _, value1, value2 -> transform(value1, value2) }
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <T, K, V, D : MutableMap<K, V>> Iterable<T>.associateTo(destination: D, transform: (T) -> Pair<K, V>, resolve: (key: K, currentValue: V, newValue: V) -> V): D {
|
||||||
|
for (element in this) {
|
||||||
|
val (key, value) = transform(element)
|
||||||
|
destination.putOrChange(key, value, resolve)
|
||||||
|
}
|
||||||
|
return destination
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <T, K, V, D : MutableMap<K, V>> Iterable<T>.associateByTo(destination: D, keySelector: (T) -> K, valueTransform: (T) -> V, resolve: (key: K, currentValue: V, newValue: V) -> V): D {
|
||||||
|
for (element in this) {
|
||||||
|
val key = keySelector(element)
|
||||||
|
val value = valueTransform(element)
|
||||||
|
destination.putOrChange(key, value, resolve)
|
||||||
|
}
|
||||||
|
return destination
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <T, K, D : MutableMap<K, T>> Iterable<T>.associateByTo(destination: D, keySelector: (T) -> K, resolve: (key: K, currentValue: T, newValue: T) -> T): D {
|
||||||
|
for (element in this) {
|
||||||
|
val key = keySelector(element)
|
||||||
|
destination.putOrChange(key, element, resolve)
|
||||||
|
}
|
||||||
|
return destination
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <T, K, V, D : MutableMap<K, V>> Iterable<T>.associateTo(destination: D, transform: (T) -> Pair<K, V>, resolve: (currentValue: V, newValue: V) -> V): D =
|
||||||
|
associateTo(destination, transform) { _, currentValue, newValue -> resolve(currentValue, newValue) }
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <T, K, V, D : MutableMap<K, V>> Iterable<T>.associateByTo(destination: D, keySelector: (T) -> K, valueTransform: (T) -> V, resolve: (currentValue: V, newValue: V) -> V): D =
|
||||||
|
associateByTo(destination, keySelector, valueTransform) { _, currentValue, newValue -> resolve(currentValue, newValue) }
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <T, K, D : MutableMap<K, T>> Iterable<T>.associateByTo(destination: D, keySelector: (T) -> K, resolve: (currentValue: T, newValue: T) -> T): D =
|
||||||
|
associateByTo(destination, keySelector) { _, currentValue, newValue -> resolve(currentValue, newValue) }
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <T, K, V> Iterable<T>.associate(transform: (T) -> Pair<K, V>, resolve: (key: K, currentValue: V, newValue: V) -> V): Map<K, V> =
|
||||||
|
associateTo(LinkedHashMap(), transform, resolve)
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <T, K, V> Iterable<T>.associateBy(keySelector: (T) -> K, valueTransform: (T) -> V, resolve: (key: K, currentValue: V, newValue: V) -> V): Map<K, V> =
|
||||||
|
associateByTo(LinkedHashMap(), keySelector, valueTransform, resolve)
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <T, K> Iterable<T>.associateBy(keySelector: (T) -> K, resolve: (key: K, currentValue: T, newValue: T) -> T): Map<K, T> =
|
||||||
|
associateByTo(LinkedHashMap(), keySelector, resolve)
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <T, K, V> Iterable<T>.associate(transform: (T) -> Pair<K, V>, resolve: (currentValue: V, newValue: V) -> V): Map<K, V> =
|
||||||
|
associateTo(LinkedHashMap(), transform, resolve)
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <T, K, V> Iterable<T>.associateBy(keySelector: (T) -> K, valueTransform: (T) -> V, resolve: (currentValue: V, newValue: V) -> V): Map<K, V> =
|
||||||
|
associateByTo(LinkedHashMap(), keySelector, valueTransform, resolve)
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <T, K> Iterable<T>.associateBy(keySelector: (T) -> K, resolve: (currentValue: T, newValue: T) -> T): Map<K, T> =
|
||||||
|
associateByTo(LinkedHashMap(), keySelector, resolve)
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <K, V, W, D : MutableMap<K, W>> Map<out K, V>.mapValuesTo(destination: D, transform: (Map.Entry<K, V>) -> W, resolve: (key: K, currentValue: W, newValue: W) -> W): D =
|
||||||
|
entries.associateByTo(destination, { it.key }, transform, resolve)
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <K, V, W, D : MutableMap<K, W>> Map<out K, V>.mapValuesTo(destination: D, transform: (key: K, value: V) -> W, resolve: (key: K, currentValue: W, newValue: W) -> W): D =
|
||||||
|
entries.associateByTo(destination, { it.key }, { (key, value) -> transform(key, value) }, resolve)
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <K, V, W, D : MutableMap<K, W>> Map<out K, V>.mapValuesTo(destination: D, transform: (Map.Entry<K, V>) -> W, resolve: (currentValue: W, newValue: W) -> W): D =
|
||||||
|
entries.associateByTo(destination, { it.key }, transform, resolve)
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <K, V, W, D : MutableMap<K, W>> Map<out K, V>.mapValuesTo(destination: D, transform: (key: K, value: V) -> W, resolve: (currentValue: W, newValue: W) -> W): D =
|
||||||
|
entries.associateByTo(destination, { it.key }, { (key, value) -> transform(key, value) }, resolve)
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <K, V, L, D : MutableMap<L, V>> Map<out K, V>.mapKeysTo(destination: D, transform: (Map.Entry<K, V>) -> L, resolve: (key: L, currentValue: V, newValue: V) -> V): D =
|
||||||
|
entries.associateByTo(destination, transform, { it.value }, resolve)
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <K, V, L, D : MutableMap<L, V>> Map<out K, V>.mapKeysTo(destination: D, transform: (key: K, value: V) -> L, resolve: (key: L, currentValue: V, newValue: V) -> V): D =
|
||||||
|
entries.associateByTo(destination, { (key, value) -> transform(key, value) }, { it.value }, resolve)
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <K, V, L, D : MutableMap<L, V>> Map<out K, V>.mapKeysTo(destination: D, transform: (Map.Entry<K, V>) -> L, resolve: (currentValue: V, newValue: V) -> V): D =
|
||||||
|
entries.associateByTo(destination, transform, { it.value }, resolve)
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <K, V, L, D : MutableMap<L, V>> Map<out K, V>.mapKeysTo(destination: D, transform: (key: K, value: V) -> L, resolve: (currentValue: V, newValue: V) -> V): D =
|
||||||
|
entries.associateByTo(destination, { (key, value) -> transform(key, value) }, { it.value }, resolve)
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <K, V, L> Map<out K, V>.mapKeys(transform: (Map.Entry<K, V>) -> L, resolve: (key: L, currentValue: V, newValue: V) -> V): Map<L, V> =
|
||||||
|
mapKeysTo(LinkedHashMap(size), transform, resolve)
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <K, V, L> Map<out K, V>.mapKeys(transform: (key: K, value: V) -> L, resolve: (key: L, currentValue: V, newValue: V) -> V): Map<L, V> =
|
||||||
|
mapKeysTo(LinkedHashMap(size), transform, resolve)
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <K, V, L> Map<out K, V>.mapKeys(transform: (Map.Entry<K, V>) -> L, resolve: (currentValue: V, newValue: V) -> V): Map<L, V> =
|
||||||
|
mapKeysTo(LinkedHashMap(size), transform, resolve)
|
||||||
|
|
||||||
|
// TODO: Docs
|
||||||
|
internal inline fun <K, V, L> Map<out K, V>.mapKeys(transform: (key: K, value: V) -> L, resolve: (currentValue: V, newValue: V) -> V): Map<L, V> =
|
||||||
|
mapKeysTo(LinkedHashMap(size), transform, resolve)
|
@ -10,6 +10,7 @@ package space.kscience.kmath.functions
|
|||||||
import space.kscience.kmath.expressions.Symbol
|
import space.kscience.kmath.expressions.Symbol
|
||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
import space.kscience.kmath.operations.Ring
|
import space.kscience.kmath.operations.Ring
|
||||||
|
import space.kscience.kmath.operations.invoke
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -76,17 +77,10 @@ public inline fun <C> LabeledPolynomialWithoutCheck(vararg pairs: Pair<Map<Symbo
|
|||||||
*
|
*
|
||||||
* @see LabeledPolynomialWithoutCheck
|
* @see LabeledPolynomialWithoutCheck
|
||||||
*/
|
*/
|
||||||
public fun <C> LabeledPolynomial(coefs: Map<Map<Symbol, UInt>, C>, add: (C, C) -> C) : LabeledPolynomial<C> {
|
public fun <C> LabeledPolynomial(coefs: Map<Map<Symbol, UInt>, C>, add: (C, C) -> C) : LabeledPolynomial<C> =
|
||||||
val fixedCoefs = mutableMapOf<Map<Symbol, UInt>, C>()
|
LabeledPolynomialAsIs(
|
||||||
|
coefs.mapKeys({ key, _ -> key.cleanUp() }, add)
|
||||||
for (entry in coefs) {
|
)
|
||||||
val key = entry.key.cleanUp()
|
|
||||||
val value = entry.value
|
|
||||||
fixedCoefs[key] = if (key in fixedCoefs) add(fixedCoefs[key]!!, value) else value
|
|
||||||
}
|
|
||||||
|
|
||||||
return LabeledPolynomial<C>(fixedCoefs)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs [LabeledPolynomial] with provided collection of [pairs] of pairs "term's signature — term's coefficient".
|
* Constructs [LabeledPolynomial] with provided collection of [pairs] of pairs "term's signature — term's coefficient".
|
||||||
@ -98,17 +92,10 @@ public fun <C> LabeledPolynomial(coefs: Map<Map<Symbol, UInt>, C>, add: (C, C) -
|
|||||||
*
|
*
|
||||||
* @see LabeledPolynomialWithoutCheck
|
* @see LabeledPolynomialWithoutCheck
|
||||||
*/
|
*/
|
||||||
public fun <C> LabeledPolynomial(pairs: Collection<Pair<Map<Symbol, UInt>, C>>, add: (C, C) -> C) : LabeledPolynomial<C> {
|
public fun <C> LabeledPolynomial(pairs: Collection<Pair<Map<Symbol, UInt>, C>>, add: (C, C) -> C) : LabeledPolynomial<C> =
|
||||||
val fixedCoefs = mutableMapOf<Map<Symbol, UInt>, C>()
|
LabeledPolynomialAsIs(
|
||||||
|
pairs.associateBy({ it.first.cleanUp() }, { it.second }, add)
|
||||||
for (entry in pairs) {
|
)
|
||||||
val key = entry.first.cleanUp()
|
|
||||||
val value = entry.second
|
|
||||||
fixedCoefs[key] = if (key in fixedCoefs) add(fixedCoefs[key]!!, value) else value
|
|
||||||
}
|
|
||||||
|
|
||||||
return LabeledPolynomial<C>(fixedCoefs)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs [LabeledPolynomial] with provided array [pairs] of pairs "term's signature — term's coefficient".
|
* Constructs [LabeledPolynomial] with provided array [pairs] of pairs "term's signature — term's coefficient".
|
||||||
@ -120,17 +107,10 @@ public fun <C> LabeledPolynomial(pairs: Collection<Pair<Map<Symbol, UInt>, C>>,
|
|||||||
*
|
*
|
||||||
* @see LabeledPolynomialWithoutCheck
|
* @see LabeledPolynomialWithoutCheck
|
||||||
*/
|
*/
|
||||||
public fun <C> LabeledPolynomial(vararg pairs: Pair<Map<Symbol, UInt>, C>, add: (C, C) -> C) : LabeledPolynomial<C> {
|
public fun <C> LabeledPolynomial(vararg pairs: Pair<Map<Symbol, UInt>, C>, add: (C, C) -> C) : LabeledPolynomial<C> =
|
||||||
val fixedCoefs = mutableMapOf<Map<Symbol, UInt>, C>()
|
LabeledPolynomialAsIs(
|
||||||
|
pairs.asIterable().associateBy({ it.first.cleanUp() }, { it.second }, add)
|
||||||
for (entry in pairs) {
|
)
|
||||||
val key = entry.first.cleanUp()
|
|
||||||
val value = entry.second
|
|
||||||
fixedCoefs[key] = if (key in fixedCoefs) add(fixedCoefs[key]!!, value) else value
|
|
||||||
}
|
|
||||||
|
|
||||||
return LabeledPolynomial<C>(fixedCoefs)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available
|
// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available
|
||||||
|
|
||||||
@ -304,7 +284,7 @@ public class DSL1LabeledPolynomialTermSignatureBuilder {
|
|||||||
*/
|
*/
|
||||||
public infix fun Symbol.inPowerOf(deg: UInt) {
|
public infix fun Symbol.inPowerOf(deg: UInt) {
|
||||||
if (deg == 0u) return
|
if (deg == 0u) return
|
||||||
signature[this] = signature.getOrElse(this) { 0u } + deg
|
signature.putOrChange(this, deg) { it -> it + deg }
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Declares power of [this] variable of degree [deg].
|
* Declares power of [this] variable of degree [deg].
|
||||||
@ -362,7 +342,7 @@ public class DSL1LabeledPolynomialBuilder<C>(
|
|||||||
* coefficients is zero at any moment the monomial won't be removed but will be left as it is.
|
* coefficients is zero at any moment the monomial won't be removed but will be left as it is.
|
||||||
*/
|
*/
|
||||||
public infix fun C.with(signature: Map<Symbol, UInt>) {
|
public infix fun C.with(signature: Map<Symbol, UInt>) {
|
||||||
coefficients[signature] = if (signature in coefficients) add(coefficients[signature]!!, this@with) else this@with
|
coefficients.putOrChange(signature, this@with, add)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Declares monomial with [this] coefficient and signature constructed by [block].
|
* Declares monomial with [this] coefficient and signature constructed by [block].
|
||||||
|
@ -7,10 +7,7 @@ package space.kscience.kmath.functions
|
|||||||
|
|
||||||
import space.kscience.kmath.expressions.Symbol
|
import space.kscience.kmath.expressions.Symbol
|
||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
import space.kscience.kmath.operations.Field
|
import space.kscience.kmath.operations.*
|
||||||
import space.kscience.kmath.operations.Ring
|
|
||||||
import space.kscience.kmath.operations.algebra
|
|
||||||
import space.kscience.kmath.operations.invoke
|
|
||||||
import kotlin.contracts.InvocationKind
|
import kotlin.contracts.InvocationKind
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
import kotlin.jvm.JvmName
|
import kotlin.jvm.JvmName
|
||||||
@ -56,7 +53,7 @@ public fun LabeledPolynomial<Double>.substitute(args: Map<Symbol, Double>): Labe
|
|||||||
val deg = degs.getOrElse(variable) { 0u }
|
val deg = degs.getOrElse(variable) { 0u }
|
||||||
if (deg == 0u) product else product * power(substitution, deg)
|
if (deg == 0u) product else product * power(substitution, deg)
|
||||||
}
|
}
|
||||||
this[newDegs] = if (newDegs in this) this[newDegs]!! + newC else newC
|
putOrChange(newDegs, newC, ::add)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -75,7 +72,7 @@ public fun <C> LabeledPolynomial<C>.substitute(ring: Ring<C>, args: Map<Symbol,
|
|||||||
val deg = degs.getOrElse(variable) { 0u }
|
val deg = degs.getOrElse(variable) { 0u }
|
||||||
if (deg == 0u) product else product * power(substitution, deg)
|
if (deg == 0u) product else product * power(substitution, deg)
|
||||||
}
|
}
|
||||||
this[newDegs] = if (newDegs in this) this[newDegs]!! + newC else newC
|
putOrChange(newDegs, newC, ::add)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -257,10 +254,7 @@ public fun <C, A : Field<C>> LabeledPolynomial<C>.antiderivativeWithRespectTo(
|
|||||||
buildMap(coefficients.size) {
|
buildMap(coefficients.size) {
|
||||||
coefficients
|
coefficients
|
||||||
.forEach { (degs, c) ->
|
.forEach { (degs, c) ->
|
||||||
val newDegs = buildMap<Symbol, UInt>(degs.size + 1) {
|
val newDegs = degs.withPutOrChanged(variable, 1u) { it -> it + 1u }
|
||||||
put(variable, 1u)
|
|
||||||
for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u })
|
|
||||||
}
|
|
||||||
put(
|
put(
|
||||||
newDegs,
|
newDegs,
|
||||||
c / multiplyByDoubling(one, newDegs[variable]!!)
|
c / multiplyByDoubling(one, newDegs[variable]!!)
|
||||||
@ -284,10 +278,7 @@ public fun <C, A : Field<C>> LabeledPolynomial<C>.nthAntiderivativeWithRespectTo
|
|||||||
buildMap(coefficients.size) {
|
buildMap(coefficients.size) {
|
||||||
coefficients
|
coefficients
|
||||||
.forEach { (degs, c) ->
|
.forEach { (degs, c) ->
|
||||||
val newDegs = buildMap<Symbol, UInt>(degs.size + 1) {
|
val newDegs = degs.withPutOrChanged(variable, order) { it -> it + order }
|
||||||
put(variable, order)
|
|
||||||
for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u })
|
|
||||||
}
|
|
||||||
put(
|
put(
|
||||||
newDegs,
|
newDegs,
|
||||||
newDegs[variable]!!.let { deg ->
|
newDegs[variable]!!.let { deg ->
|
||||||
@ -314,10 +305,7 @@ public fun <C, A : Field<C>> LabeledPolynomial<C>.nthAntiderivativeWithRespectTo
|
|||||||
buildMap(coefficients.size) {
|
buildMap(coefficients.size) {
|
||||||
coefficients
|
coefficients
|
||||||
.forEach { (degs, c) ->
|
.forEach { (degs, c) ->
|
||||||
val newDegs = buildMap<Symbol, UInt>(degs.size + 1) {
|
val newDegs = mergeBy(degs, filteredVariablesAndOrders) { deg, order -> deg + order }
|
||||||
for ((variable, order) in filteredVariablesAndOrders) put(variable, order)
|
|
||||||
for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u })
|
|
||||||
}
|
|
||||||
put(
|
put(
|
||||||
newDegs,
|
newDegs,
|
||||||
filteredVariablesAndOrders.entries.fold(c) { acc1, (index, order) ->
|
filteredVariablesAndOrders.entries.fold(c) { acc1, (index, order) ->
|
||||||
|
@ -75,17 +75,10 @@ public inline fun <C> NumberedPolynomialWithoutCheck(vararg pairs: Pair<List<UIn
|
|||||||
*
|
*
|
||||||
* @see NumberedPolynomialWithoutCheck
|
* @see NumberedPolynomialWithoutCheck
|
||||||
*/
|
*/
|
||||||
public fun <C> NumberedPolynomial(coefs: Map<List<UInt>, C>, add: (C, C) -> C) : NumberedPolynomial<C> {
|
public fun <C> NumberedPolynomial(coefs: Map<List<UInt>, C>, add: (C, C) -> C) : NumberedPolynomial<C> =
|
||||||
val fixedCoefs = mutableMapOf<List<UInt>, C>()
|
NumberedPolynomialAsIs(
|
||||||
|
coefs.mapKeys({ key, _ -> key.cleanUp() }, add)
|
||||||
for (entry in coefs) {
|
)
|
||||||
val key = entry.key.cleanUp()
|
|
||||||
val value = entry.value
|
|
||||||
fixedCoefs[key] = if (key in fixedCoefs) add(fixedCoefs[key]!!, value) else value
|
|
||||||
}
|
|
||||||
|
|
||||||
return NumberedPolynomial<C>(fixedCoefs)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs [NumberedPolynomial] with provided collection of [pairs] of pairs "term's signature — term's coefficient".
|
* Constructs [NumberedPolynomial] with provided collection of [pairs] of pairs "term's signature — term's coefficient".
|
||||||
@ -97,17 +90,10 @@ public fun <C> NumberedPolynomial(coefs: Map<List<UInt>, C>, add: (C, C) -> C) :
|
|||||||
*
|
*
|
||||||
* @see NumberedPolynomialWithoutCheck
|
* @see NumberedPolynomialWithoutCheck
|
||||||
*/
|
*/
|
||||||
public fun <C> NumberedPolynomial(pairs: Collection<Pair<List<UInt>, C>>, add: (C, C) -> C) : NumberedPolynomial<C> {
|
public fun <C> NumberedPolynomial(pairs: Collection<Pair<List<UInt>, C>>, add: (C, C) -> C) : NumberedPolynomial<C> =
|
||||||
val fixedCoefs = mutableMapOf<List<UInt>, C>()
|
NumberedPolynomialAsIs(
|
||||||
|
pairs.associateBy({ it.first.cleanUp() }, { it.second }, add)
|
||||||
for (entry in pairs) {
|
)
|
||||||
val key = entry.first.cleanUp()
|
|
||||||
val value = entry.second
|
|
||||||
fixedCoefs[key] = if (key in fixedCoefs) add(fixedCoefs[key]!!, value) else value
|
|
||||||
}
|
|
||||||
|
|
||||||
return NumberedPolynomial<C>(fixedCoefs)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs [NumberedPolynomial] with provided array [pairs] of pairs "term's signature — term's coefficient".
|
* Constructs [NumberedPolynomial] with provided array [pairs] of pairs "term's signature — term's coefficient".
|
||||||
@ -119,17 +105,10 @@ public fun <C> NumberedPolynomial(pairs: Collection<Pair<List<UInt>, C>>, add: (
|
|||||||
*
|
*
|
||||||
* @see NumberedPolynomialWithoutCheck
|
* @see NumberedPolynomialWithoutCheck
|
||||||
*/
|
*/
|
||||||
public fun <C> NumberedPolynomial(vararg pairs: Pair<List<UInt>, C>, add: (C, C) -> C) : NumberedPolynomial<C> {
|
public fun <C> NumberedPolynomial(vararg pairs: Pair<List<UInt>, C>, add: (C, C) -> C) : NumberedPolynomial<C> =
|
||||||
val fixedCoefs = mutableMapOf<List<UInt>, C>()
|
NumberedPolynomialAsIs(
|
||||||
|
pairs.asIterable().associateBy({ it.first.cleanUp() }, { it.second }, add)
|
||||||
for (entry in pairs) {
|
)
|
||||||
val key = entry.first.cleanUp()
|
|
||||||
val value = entry.second
|
|
||||||
fixedCoefs[key] = if (key in fixedCoefs) add(fixedCoefs[key]!!, value) else value
|
|
||||||
}
|
|
||||||
|
|
||||||
return NumberedPolynomial<C>(fixedCoefs)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available
|
// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available
|
||||||
|
|
||||||
@ -349,7 +328,7 @@ public class DSL1NumberedPolynomialBuilder<C>(
|
|||||||
* coefficients is zero at any moment the monomial won't be removed but will be left as it is.
|
* coefficients is zero at any moment the monomial won't be removed but will be left as it is.
|
||||||
*/
|
*/
|
||||||
public infix fun C.with(signature: List<UInt>) {
|
public infix fun C.with(signature: List<UInt>) {
|
||||||
coefficients[signature] = if (signature in coefficients) add(coefficients[signature]!!, this@with) else this@with
|
coefficients.putOrChange(signature, this@with, add)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Declares monomial with [this] coefficient and signature constructed by [block].
|
* Declares monomial with [this] coefficient and signature constructed by [block].
|
||||||
|
@ -58,7 +58,7 @@ public fun NumberedPolynomial<Double>.substitute(args: Map<Int, Double>): Number
|
|||||||
val deg = degs.getOrElse(variable) { 0u }
|
val deg = degs.getOrElse(variable) { 0u }
|
||||||
if (deg == 0u) product else product * substitution.pow(deg.toInt())
|
if (deg == 0u) product else product * substitution.pow(deg.toInt())
|
||||||
}
|
}
|
||||||
this[newDegs] = if (newDegs !in this) newC else this[newDegs]!! + newC
|
putOrChange(newDegs, newC) { it -> it + newC }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -76,7 +76,7 @@ public fun <C> NumberedPolynomial<C>.substitute(ring: Ring<C>, args: Map<Int, C>
|
|||||||
val deg = degs.getOrElse(variable) { 0u }
|
val deg = degs.getOrElse(variable) { 0u }
|
||||||
if (deg == 0u) product else product * power(substitution, deg)
|
if (deg == 0u) product else product * power(substitution, deg)
|
||||||
}
|
}
|
||||||
this[newDegs] = if (newDegs !in this) newC else this[newDegs]!! + newC
|
putOrChange(newDegs, newC) { it -> it + newC }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -158,8 +158,7 @@ public fun NumberedPolynomial<Double>.substitute(args: Buffer<Double>): Numbered
|
|||||||
val deg = degs[variable]
|
val deg = degs[variable]
|
||||||
if (deg == 0u) product else product * args[variable].pow(deg.toInt())
|
if (deg == 0u) product else product * args[variable].pow(deg.toInt())
|
||||||
}
|
}
|
||||||
if (newDegs !in this) this[newDegs] = newC
|
putOrChange(newDegs, newC) { it -> it + newC }
|
||||||
else this[newDegs] = this[newDegs]!! + newC
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -183,8 +182,7 @@ public fun <C> NumberedPolynomial<C>.substitute(ring: Ring<C>, args: Buffer<C>):
|
|||||||
val deg = degs[variable]
|
val deg = degs[variable]
|
||||||
if (deg == 0u) product else product * power(args[variable], deg)
|
if (deg == 0u) product else product * power(args[variable], deg)
|
||||||
}
|
}
|
||||||
if (newDegs !in this) this[newDegs] = newC
|
putOrChange(newDegs, newC) { it -> it + newC }
|
||||||
else this[newDegs] = this[newDegs]!! + newC
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -23,8 +23,8 @@ class NumberedConstructorsTest {
|
|||||||
),
|
),
|
||||||
Int.algebra.numberedPolynomialSpace {
|
Int.algebra.numberedPolynomialSpace {
|
||||||
NumberedPolynomialDSL1 {
|
NumberedPolynomialDSL1 {
|
||||||
5 { 1 pow 2u; 3 pow 3u }
|
5 { 0 pow 2u; 2 pow 3u }
|
||||||
(-6) { 2 pow 1u }
|
(-6) { 1 pow 1u }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"test 1"
|
"test 1"
|
||||||
@ -47,8 +47,8 @@ class NumberedConstructorsTest {
|
|||||||
),
|
),
|
||||||
Int.algebra.numberedPolynomialSpace {
|
Int.algebra.numberedPolynomialSpace {
|
||||||
NumberedPolynomialDSL1 {
|
NumberedPolynomialDSL1 {
|
||||||
5 { 1 pow 1u; 1 pow 1u }
|
5 { 0 pow 1u; 0 pow 1u }
|
||||||
(-6) { 1 pow 2u }
|
(-6) { 0 pow 2u }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"test 3"
|
"test 3"
|
||||||
@ -59,8 +59,8 @@ class NumberedConstructorsTest {
|
|||||||
),
|
),
|
||||||
Int.algebra.numberedPolynomialSpace {
|
Int.algebra.numberedPolynomialSpace {
|
||||||
NumberedPolynomialDSL1 {
|
NumberedPolynomialDSL1 {
|
||||||
5 { 1 pow 1u; 1 pow 1u }
|
5 { 0 pow 1u; 0 pow 1u }
|
||||||
(-6) { 1 pow 2u; 3 pow 0u }
|
(-6) { 0 pow 2u; 2 pow 0u }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"test 3"
|
"test 3"
|
||||||
|
Loading…
Reference in New Issue
Block a user